baseguard 1.0.4 → 1.0.6

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 (84) hide show
  1. package/dist/ai/gemini-analyzer.d.ts.map +1 -1
  2. package/dist/ai/gemini-analyzer.js +1 -1
  3. package/dist/ai/gemini-analyzer.js.map +1 -1
  4. package/dist/ai/gemini-code-fixer.d.ts.map +1 -1
  5. package/dist/ai/gemini-code-fixer.js +2 -7
  6. package/dist/ai/gemini-code-fixer.js.map +1 -1
  7. package/dist/ai/jules-implementer.d.ts +8 -0
  8. package/dist/ai/jules-implementer.d.ts.map +1 -1
  9. package/dist/ai/jules-implementer.js +115 -17
  10. package/dist/ai/jules-implementer.js.map +1 -1
  11. package/dist/commands/fix.d.ts.map +1 -1
  12. package/dist/commands/fix.js +5 -1
  13. package/dist/commands/fix.js.map +1 -1
  14. package/dist/core/baseline-checker.d.ts.map +1 -1
  15. package/dist/core/baseline-checker.js +6 -4
  16. package/dist/core/baseline-checker.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/ai/__tests__/gemini-analyzer.test.ts +0 -181
  19. package/src/ai/agentkit-orchestrator.ts +0 -534
  20. package/src/ai/fix-manager.ts +0 -362
  21. package/src/ai/gemini-analyzer.ts +0 -665
  22. package/src/ai/gemini-code-fixer.ts +0 -539
  23. package/src/ai/index.ts +0 -4
  24. package/src/ai/jules-implementer.ts +0 -504
  25. package/src/ai/unified-code-fixer.ts +0 -347
  26. package/src/commands/automation.ts +0 -344
  27. package/src/commands/check.ts +0 -298
  28. package/src/commands/config.ts +0 -584
  29. package/src/commands/fix.ts +0 -264
  30. package/src/commands/index.ts +0 -7
  31. package/src/commands/init.ts +0 -156
  32. package/src/commands/status.ts +0 -307
  33. package/src/core/api-key-manager.ts +0 -298
  34. package/src/core/baseguard.ts +0 -757
  35. package/src/core/baseline-checker.ts +0 -564
  36. package/src/core/cache-manager.ts +0 -272
  37. package/src/core/configuration-recovery.ts +0 -672
  38. package/src/core/configuration.ts +0 -596
  39. package/src/core/debug-logger.ts +0 -590
  40. package/src/core/directory-filter.ts +0 -421
  41. package/src/core/error-handler.ts +0 -518
  42. package/src/core/file-processor.ts +0 -338
  43. package/src/core/gitignore-manager.ts +0 -169
  44. package/src/core/graceful-degradation-manager.ts +0 -596
  45. package/src/core/index.ts +0 -17
  46. package/src/core/lazy-loader.ts +0 -317
  47. package/src/core/logger.ts +0 -0
  48. package/src/core/memory-manager.ts +0 -290
  49. package/src/core/parser-worker.ts +0 -33
  50. package/src/core/startup-optimizer.ts +0 -246
  51. package/src/core/system-error-handler.ts +0 -755
  52. package/src/git/automation-engine.ts +0 -361
  53. package/src/git/github-manager.ts +0 -190
  54. package/src/git/hook-manager.ts +0 -210
  55. package/src/git/index.ts +0 -4
  56. package/src/index.ts +0 -8
  57. package/src/parsers/feature-validator.ts +0 -559
  58. package/src/parsers/index.ts +0 -8
  59. package/src/parsers/parser-manager.ts +0 -418
  60. package/src/parsers/parser.ts +0 -26
  61. package/src/parsers/react-parser-optimized.ts +0 -161
  62. package/src/parsers/react-parser.ts +0 -359
  63. package/src/parsers/svelte-parser.ts +0 -510
  64. package/src/parsers/vanilla-parser.ts +0 -685
  65. package/src/parsers/vue-parser.ts +0 -476
  66. package/src/types/index.ts +0 -96
  67. package/src/ui/components.ts +0 -567
  68. package/src/ui/help.ts +0 -193
  69. package/src/ui/index.ts +0 -4
  70. package/src/ui/prompts.ts +0 -681
  71. package/src/ui/terminal-header.ts +0 -59
  72. package/tests/e2e/baseguard.e2e.test.ts +0 -516
  73. package/tests/e2e/cross-platform.e2e.test.ts +0 -420
  74. package/tests/e2e/git-integration.e2e.test.ts +0 -487
  75. package/tests/fixtures/react-project/package.json +0 -14
  76. package/tests/fixtures/react-project/src/App.css +0 -76
  77. package/tests/fixtures/react-project/src/App.tsx +0 -77
  78. package/tests/fixtures/svelte-project/package.json +0 -11
  79. package/tests/fixtures/svelte-project/src/App.svelte +0 -369
  80. package/tests/fixtures/vanilla-project/index.html +0 -76
  81. package/tests/fixtures/vanilla-project/script.js +0 -331
  82. package/tests/fixtures/vanilla-project/styles.css +0 -359
  83. package/tests/fixtures/vue-project/package.json +0 -12
  84. package/tests/fixtures/vue-project/src/App.vue +0 -216
@@ -1,307 +0,0 @@
1
- import { BaseGuard } from '../core/baseguard.js';
2
- import { ConfigurationManager } from '../core/configuration.js';
3
- import { ConfigurationRecovery } from '../core/configuration-recovery.js';
4
- import { GracefulDegradationManager } from '../core/graceful-degradation-manager.js';
5
- import { SystemErrorHandler } from '../core/system-error-handler.js';
6
- import { logger } from '../core/debug-logger.js';
7
- import { UIComponents } from '../ui/components.js';
8
- import chalk from 'chalk';
9
-
10
- /**
11
- * Show BaseGuard system status and health
12
- */
13
- export async function status(options: {
14
- verbose?: boolean;
15
- services?: boolean;
16
- config?: boolean;
17
- errors?: boolean;
18
- }): Promise<void> {
19
- const categoryLogger = logger.createCategoryLogger('status-command');
20
-
21
- try {
22
- UIComponents.showHeader();
23
- console.log(chalk.cyan('🔍 BaseGuard System Status\n'));
24
-
25
- // Load configuration with recovery if needed
26
- let config;
27
- try {
28
- config = await ConfigurationManager.load();
29
- } catch (error) {
30
- console.log(chalk.red('❌ Configuration Error'));
31
- console.log(chalk.dim(` ${error instanceof Error ? error.message : 'Unknown error'}`));
32
-
33
- if (options.config) {
34
- console.log(chalk.cyan('\n🔧 Configuration Recovery Options:'));
35
- console.log(chalk.cyan(' • Run "base config recover" to attempt automatic recovery'));
36
- console.log(chalk.cyan(' • Run "base init" to create a new configuration'));
37
- console.log(chalk.cyan(' • Check .baseguardrc.json file manually'));
38
- }
39
-
40
- return;
41
- }
42
-
43
- // Initialize BaseGuard
44
- const baseGuard = new BaseGuard(config);
45
-
46
- // Show system health
47
- const health = await baseGuard.getHealthStatus();
48
-
49
- // Overall status
50
- const statusIcon = health.overall === 'healthy' ? '✅' : health.overall === 'degraded' ? '⚠️' : '❌';
51
- const statusColor = health.overall === 'healthy' ? chalk.green : health.overall === 'degraded' ? chalk.yellow : chalk.red;
52
-
53
- console.log(statusColor(`${statusIcon} Overall Status: ${health.overall.toUpperCase()}`));
54
- console.log(chalk.dim(` Degradation Mode: ${health.degradationMode}`));
55
-
56
- // Component status
57
- console.log(chalk.cyan('\n📊 Component Status:'));
58
- for (const [component, status] of Object.entries(health.components)) {
59
- const componentIcon = status.status === 'healthy' ? '✅' : status.status === 'degraded' ? '⚠️' : '❌';
60
- console.log(` ${componentIcon} ${component}: ${status.status}`);
61
-
62
- if (options.verbose && status.details) {
63
- if (status.details.errors?.length > 0) {
64
- console.log(chalk.dim(` Errors: ${status.details.errors.slice(0, 3).join(', ')}`));
65
- }
66
- if (status.details.error) {
67
- console.log(chalk.dim(` Error: ${status.details.error}`));
68
- }
69
- if (status.details.lastCheck) {
70
- const age = Math.round((Date.now() - status.details.lastCheck) / 1000);
71
- console.log(chalk.dim(` Last Check: ${age}s ago`));
72
- }
73
- }
74
- }
75
-
76
- // Service status (if requested)
77
- if (options.services) {
78
- console.log(chalk.cyan('\n🌐 Service Status:'));
79
- const serviceStatus = GracefulDegradationManager.getServiceStatus();
80
-
81
- for (const [service, info] of serviceStatus) {
82
- const serviceIcon = info.available ? '✅' : '❌';
83
- const age = Math.round((Date.now() - info.lastCheck) / 1000);
84
- console.log(` ${serviceIcon} ${service}: ${info.available ? 'Available' : 'Unavailable'} (${age}s ago)`);
85
-
86
- if (!info.available && info.error && options.verbose) {
87
- console.log(chalk.dim(` Error: ${info.error}`));
88
- }
89
- }
90
-
91
- // Refresh service status
92
- console.log(chalk.dim('\n🔄 Refreshing service status...'));
93
- await GracefulDegradationManager.refreshServiceStatus();
94
- }
95
-
96
- // Configuration status (if requested)
97
- if (options.config) {
98
- console.log(chalk.cyan('\n⚙️ Configuration Status:'));
99
-
100
- const configIntegrity = await ConfigurationRecovery.validateIntegrity();
101
- const configIcon = configIntegrity.valid ? '✅' : '❌';
102
- console.log(` ${configIcon} Configuration File: ${configIntegrity.valid ? 'Valid' : 'Invalid'}`);
103
-
104
- if (!configIntegrity.valid) {
105
- console.log(chalk.red(' Errors:'));
106
- configIntegrity.errors.forEach(error => {
107
- console.log(chalk.red(` • ${error}`));
108
- });
109
-
110
- console.log(chalk.cyan(' Suggestions:'));
111
- configIntegrity.suggestions.forEach(suggestion => {
112
- console.log(chalk.cyan(` • ${suggestion}`));
113
- });
114
- }
115
-
116
- // Show configuration details
117
- if (options.verbose) {
118
- console.log(chalk.dim('\n Configuration Details:'));
119
- console.log(chalk.dim(` Version: ${config.version}`));
120
- console.log(chalk.dim(` Targets: ${config.targets.length} browser(s)`));
121
- console.log(chalk.dim(` API Keys: Jules ${config.apiKeys.jules ? '✓' : '✗'}, Gemini ${config.apiKeys.gemini ? '✓' : '✗'}`));
122
- console.log(chalk.dim(` Automation: ${config.automation.enabled ? 'Enabled' : 'Disabled'}`));
123
- }
124
-
125
- // Show available backups
126
- const backups = await ConfigurationRecovery.listBackups();
127
- if (backups.length > 0) {
128
- console.log(chalk.dim(`\n Available Backups: ${backups.length}`));
129
- if (options.verbose) {
130
- backups.slice(0, 3).forEach(backup => {
131
- console.log(chalk.dim(` • ${backup.timestamp.toLocaleString()} (${backup.source})`));
132
- });
133
- }
134
- }
135
- }
136
-
137
- // Error summary (if requested)
138
- if (options.errors) {
139
- console.log(chalk.cyan('\n🚨 Error Summary:'));
140
-
141
- const errorSummary = logger.getErrorSummary();
142
- console.log(` Total Errors: ${errorSummary.totalErrors}`);
143
- console.log(` Total Warnings: ${errorSummary.totalWarnings}`);
144
-
145
- if (errorSummary.totalErrors > 0) {
146
- console.log(chalk.red('\n Error Categories:'));
147
- for (const [category, count] of Object.entries(errorSummary.errorsByCategory)) {
148
- console.log(chalk.red(` ${category}: ${count}`));
149
- }
150
-
151
- if (options.verbose && errorSummary.recentErrors.length > 0) {
152
- console.log(chalk.red('\n Recent Errors:'));
153
- errorSummary.recentErrors.slice(0, 3).forEach(error => {
154
- console.log(chalk.red(` • ${error.message} (${error.category})`));
155
- });
156
- }
157
- }
158
-
159
- // System error handler status
160
- const systemErrorSummary = SystemErrorHandler.getErrorSummary();
161
- if (systemErrorSummary.total > 0) {
162
- console.log(chalk.yellow('\n System Errors:'));
163
- console.log(` Total: ${systemErrorSummary.total}`);
164
- console.log(` Critical: ${systemErrorSummary.critical}`);
165
- console.log(` Recoverable: ${systemErrorSummary.recoverable}`);
166
-
167
- if (options.verbose) {
168
- console.log(chalk.yellow('\n By Severity:'));
169
- for (const [severity, count] of Object.entries(systemErrorSummary.bySeverity)) {
170
- if (count > 0) {
171
- console.log(` ${severity}: ${count}`);
172
- }
173
- }
174
- }
175
- }
176
- }
177
-
178
- // Recommendations
179
- if (health.recommendations.length > 0) {
180
- console.log(chalk.cyan('\n💡 Recommendations:'));
181
- health.recommendations.forEach(rec => {
182
- console.log(chalk.cyan(` • ${rec}`));
183
- });
184
- }
185
-
186
- // Show degradation mode details
187
- const mode = GracefulDegradationManager.getCurrentMode();
188
- if (mode && mode.name !== 'Full Functionality') {
189
- console.log(chalk.yellow(`\n⚠️ Currently in ${mode.name} Mode`));
190
- console.log(chalk.dim(` ${mode.description}`));
191
-
192
- if (mode.limitations.length > 0) {
193
- console.log(chalk.yellow('\n Limitations:'));
194
- mode.limitations.forEach(limitation => {
195
- console.log(chalk.yellow(` • ${limitation}`));
196
- });
197
- }
198
-
199
- console.log(chalk.cyan('\n Available Features:'));
200
- if (mode.capabilities.baselineChecking) {
201
- console.log(chalk.green(' ✅ Baseline compatibility checking'));
202
- }
203
- if (mode.capabilities.caching) {
204
- console.log(chalk.green(' ✅ Result caching'));
205
- }
206
- if (!mode.capabilities.aiAnalysis) {
207
- console.log(chalk.yellow(' ⚠️ AI analysis disabled'));
208
- }
209
- if (!mode.capabilities.autoFix) {
210
- console.log(chalk.yellow(' ⚠️ Auto-fixing disabled'));
211
- }
212
- }
213
-
214
- // Performance info
215
- if (options.verbose) {
216
- const memoryUsage = process.memoryUsage();
217
- const uptime = process.uptime();
218
-
219
- console.log(chalk.cyan('\n📈 Performance Info:'));
220
- console.log(` Uptime: ${Math.round(uptime)}s`);
221
- console.log(` Memory: ${Math.round(memoryUsage.heapUsed / 1024 / 1024)}MB used / ${Math.round(memoryUsage.heapTotal / 1024 / 1024)}MB total`);
222
- console.log(` Platform: ${process.platform} ${process.arch}`);
223
- console.log(` Node.js: ${process.version}`);
224
- }
225
-
226
- // Quick actions
227
- console.log(chalk.cyan('\n🔧 Quick Actions:'));
228
- const actions = [];
229
-
230
- if (health.overall !== 'healthy') {
231
- actions.push('Run "base config recover" to attempt automatic recovery');
232
- }
233
-
234
- if (!mode?.capabilities.aiAnalysis) {
235
- actions.push('Check network connectivity to restore AI features');
236
- }
237
-
238
- const errorSummary = logger.getErrorSummary();
239
- if (errorSummary.totalErrors > 5) {
240
- actions.push('Run with --errors flag to see detailed error information');
241
- }
242
-
243
- actions.push('Run "base check" to scan for compatibility issues');
244
- actions.push('Run "base status --verbose" for detailed information');
245
-
246
- actions.forEach(action => {
247
- console.log(chalk.cyan(` • ${action}`));
248
- });
249
-
250
- } catch (error) {
251
- categoryLogger.error('Status command failed', { error });
252
-
253
- console.log(chalk.red('\n❌ Failed to get system status'));
254
- console.log(chalk.red(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
255
-
256
- console.log(chalk.cyan('\n🔧 Recovery Options:'));
257
- console.log(chalk.cyan(' • Run "base init" to reinitialize BaseGuard'));
258
- console.log(chalk.cyan(' • Check file permissions in your project directory'));
259
- console.log(chalk.cyan(' • Verify BaseGuard installation: npm list baseguard'));
260
-
261
- process.exit(1);
262
- }
263
- }
264
-
265
- /**
266
- * Show detailed system diagnostics
267
- */
268
- export async function diagnostics(): Promise<void> {
269
- const categoryLogger = logger.createCategoryLogger('diagnostics');
270
-
271
- try {
272
- console.log(chalk.cyan('🔬 BaseGuard System Diagnostics\n'));
273
-
274
- // Generate comprehensive debug report
275
- const reportFile = await logger.generateDebugReport();
276
- console.log(chalk.green(`✅ Debug report generated: ${reportFile}`));
277
-
278
- // Show configuration recovery wizard
279
- console.log(chalk.cyan('\n🔧 Running Configuration Recovery Wizard...'));
280
- await ConfigurationRecovery.runRecoveryWizard();
281
-
282
- // Show service status
283
- console.log(chalk.cyan('\n🌐 Checking Service Availability...'));
284
- await GracefulDegradationManager.refreshServiceStatus();
285
-
286
- // Show error log summary
287
- const loggerErrorSummary = logger.getErrorSummary();
288
- if (loggerErrorSummary.totalErrors > 0) {
289
- console.log(chalk.yellow(`\n⚠️ Found ${loggerErrorSummary.totalErrors} errors in logs`));
290
- console.log(chalk.cyan('Recent errors:'));
291
- loggerErrorSummary.recentErrors.slice(0, 5).forEach(error => {
292
- console.log(chalk.red(` • ${error.message} (${error.category})`));
293
- });
294
- }
295
-
296
- // Cleanup old files
297
- console.log(chalk.cyan('\n🧹 Cleaning up old files...'));
298
- await logger.cleanupOldLogs();
299
- await GracefulDegradationManager.cleanupCache();
300
-
301
- console.log(chalk.green('\n✅ Diagnostics completed'));
302
-
303
- } catch (error) {
304
- categoryLogger.error('Diagnostics failed', { error });
305
- console.log(chalk.red(`\n❌ Diagnostics failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
306
- }
307
- }
@@ -1,298 +0,0 @@
1
- import { ConfigurationManager } from './configuration.js';
2
- import { UIComponents } from '../ui/components.js';
3
-
4
- /**
5
- * API key validation patterns and utilities
6
- */
7
- export class ApiKeyManager {
8
- /**
9
- * Validate Jules API key format
10
- */
11
- static validateJulesApiKey(apiKey: string): { valid: boolean; error?: string } {
12
- if (!apiKey || typeof apiKey !== 'string') {
13
- return { valid: false, error: 'API key is required' };
14
- }
15
-
16
- const trimmed = apiKey.trim();
17
-
18
- if (trimmed.length < 10) {
19
- return { valid: false, error: 'API key seems too short' };
20
- }
21
-
22
- if (trimmed.length > 200) {
23
- return { valid: false, error: 'API key seems too long' };
24
- }
25
-
26
- // Basic format validation - Jules keys might have specific patterns
27
- if (!/^[A-Za-z0-9_.-]+$/.test(trimmed)) {
28
- return { valid: false, error: 'API key contains invalid characters' };
29
- }
30
-
31
- return { valid: true };
32
- }
33
-
34
- /**
35
- * Validate Gemini API key format
36
- */
37
- static validateGeminiApiKey(apiKey: string): { valid: boolean; error?: string } {
38
- if (!apiKey || typeof apiKey !== 'string') {
39
- return { valid: false, error: 'API key is required' };
40
- }
41
-
42
- const trimmed = apiKey.trim();
43
-
44
- if (trimmed.length < 30) {
45
- return { valid: false, error: 'Gemini API key seems too short' };
46
- }
47
-
48
- if (trimmed.length > 100) {
49
- return { valid: false, error: 'Gemini API key seems too long' };
50
- }
51
-
52
- // Gemini API keys typically start with "AIza"
53
- if (!trimmed.startsWith('AIza')) {
54
- return { valid: false, error: 'Gemini API keys typically start with "AIza"' };
55
- }
56
-
57
- // Basic format validation
58
- if (!/^[A-Za-z0-9_-]+$/.test(trimmed)) {
59
- return { valid: false, error: 'API key contains invalid characters' };
60
- }
61
-
62
- return { valid: true };
63
- }
64
-
65
- /**
66
- * Test Jules API key connectivity
67
- */
68
- static async testJulesApiKey(apiKey: string): Promise<{ success: boolean; error?: string }> {
69
- try {
70
- // Validate format first
71
- const validation = this.validateJulesApiKey(apiKey);
72
- if (!validation.valid) {
73
- return { success: false, error: validation.error };
74
- }
75
-
76
- // Test connectivity with a simple API call
77
- const response = await fetch('https://jules.googleapis.com/v1alpha/sessions', {
78
- method: 'GET',
79
- headers: {
80
- 'X-Goog-Api-Key': apiKey.trim(),
81
- 'Content-Type': 'application/json'
82
- }
83
- });
84
-
85
- if (response.status === 401) {
86
- return { success: false, error: 'Invalid API key or insufficient permissions' };
87
- }
88
-
89
- if (response.status === 403) {
90
- return { success: false, error: 'API key does not have required permissions' };
91
- }
92
-
93
- if (response.status === 429) {
94
- return { success: false, error: 'Rate limit exceeded. Please try again later' };
95
- }
96
-
97
- if (!response.ok && response.status !== 404) {
98
- return { success: false, error: `API error: ${response.status} ${response.statusText}` };
99
- }
100
-
101
- // 404 is acceptable for a test call to sessions endpoint
102
- return { success: true };
103
-
104
- } catch (error) {
105
- if (error instanceof Error) {
106
- if (error.message.includes('fetch')) {
107
- return { success: false, error: 'Network error. Please check your internet connection' };
108
- }
109
- return { success: false, error: error.message };
110
- }
111
- return { success: false, error: 'Unknown error occurred during API test' };
112
- }
113
- }
114
-
115
- /**
116
- * Test Gemini API key connectivity
117
- */
118
- static async testGeminiApiKey(apiKey: string): Promise<{ success: boolean; error?: string }> {
119
- try {
120
- // Validate format first
121
- const validation = this.validateGeminiApiKey(apiKey);
122
- if (!validation.valid) {
123
- return { success: false, error: validation.error };
124
- }
125
-
126
- // Test connectivity with a simple API call
127
- const response = await fetch('https://generativelanguage.googleapis.com/v1beta/models', {
128
- method: 'GET',
129
- headers: {
130
- 'x-goog-api-key': apiKey.trim()
131
- }
132
- });
133
-
134
- if (response.status === 401) {
135
- return { success: false, error: 'Invalid API key' };
136
- }
137
-
138
- if (response.status === 403) {
139
- return { success: false, error: 'API key does not have required permissions' };
140
- }
141
-
142
- if (response.status === 429) {
143
- return { success: false, error: 'Rate limit exceeded. Please try again later' };
144
- }
145
-
146
- if (!response.ok) {
147
- return { success: false, error: `API error: ${response.status} ${response.statusText}` };
148
- }
149
-
150
- // Verify we can parse the response
151
- const data = await response.json();
152
- if (!data.models || !Array.isArray(data.models)) {
153
- return { success: false, error: 'Unexpected API response format' };
154
- }
155
-
156
- return { success: true };
157
-
158
- } catch (error) {
159
- if (error instanceof Error) {
160
- if (error.message.includes('fetch')) {
161
- return { success: false, error: 'Network error. Please check your internet connection' };
162
- }
163
- return { success: false, error: error.message };
164
- }
165
- return { success: false, error: 'Unknown error occurred during API test' };
166
- }
167
- }
168
-
169
- /**
170
- * Store API keys securely in configuration
171
- */
172
- static async storeApiKeys(keys: { jules?: string; gemini?: string }): Promise<void> {
173
- const config = await ConfigurationManager.load();
174
-
175
- if (keys.jules) {
176
- config.apiKeys.jules = keys.jules.trim();
177
- }
178
-
179
- if (keys.gemini) {
180
- config.apiKeys.gemini = keys.gemini.trim();
181
- }
182
-
183
- await ConfigurationManager.save(config);
184
- }
185
-
186
- /**
187
- * Get stored API keys
188
- */
189
- static async getStoredApiKeys(): Promise<{ jules: string | null; gemini: string | null }> {
190
- const config = await ConfigurationManager.load();
191
- return {
192
- jules: config.apiKeys.jules,
193
- gemini: config.apiKeys.gemini
194
- };
195
- }
196
-
197
- /**
198
- * Check if API keys are configured
199
- */
200
- static async hasApiKeys(): Promise<{ jules: boolean; gemini: boolean }> {
201
- const keys = await this.getStoredApiKeys();
202
- return {
203
- jules: !!keys.jules,
204
- gemini: !!keys.gemini
205
- };
206
- }
207
-
208
- /**
209
- * Clear stored API keys
210
- */
211
- static async clearApiKeys(): Promise<void> {
212
- const config = await ConfigurationManager.load();
213
- config.apiKeys.jules = null;
214
- config.apiKeys.gemini = null;
215
- await ConfigurationManager.save(config);
216
- }
217
-
218
- /**
219
- * Validate and test all stored API keys
220
- */
221
- static async validateStoredKeys(): Promise<{
222
- jules: { valid: boolean; error?: string };
223
- gemini: { valid: boolean; error?: string };
224
- }> {
225
- const keys = await this.getStoredApiKeys();
226
-
227
- const results = {
228
- jules: { valid: false, error: 'No API key configured' },
229
- gemini: { valid: false, error: 'No API key configured' }
230
- };
231
-
232
- if (keys.jules) {
233
- const julesResult = await this.testJulesApiKey(keys.jules);
234
- results.jules = { valid: julesResult.success, error: julesResult.error || '' };
235
- }
236
-
237
- if (keys.gemini) {
238
- const geminiResult = await this.testGeminiApiKey(keys.gemini);
239
- results.gemini = { valid: geminiResult.success, error: geminiResult.error || '' };
240
- }
241
-
242
- return results;
243
- }
244
-
245
- /**
246
- * Get API key status for display
247
- */
248
- static async getApiKeyStatus(): Promise<{
249
- jules: 'configured' | 'missing' | 'invalid';
250
- gemini: 'configured' | 'missing' | 'invalid';
251
- }> {
252
- const keys = await this.getStoredApiKeys();
253
- const status: {
254
- jules: 'configured' | 'missing' | 'invalid';
255
- gemini: 'configured' | 'missing' | 'invalid';
256
- } = {
257
- jules: 'missing',
258
- gemini: 'missing'
259
- };
260
-
261
- if (keys.jules) {
262
- const validation = this.validateJulesApiKey(keys.jules);
263
- status.jules = validation.valid ? 'configured' : 'invalid';
264
- }
265
-
266
- if (keys.gemini) {
267
- const validation = this.validateGeminiApiKey(keys.gemini);
268
- status.gemini = validation.valid ? 'configured' : 'invalid';
269
- }
270
-
271
- return status;
272
- }
273
-
274
- /**
275
- * Show helpful error messages for API failures
276
- */
277
- static showApiErrorHelp(service: 'jules' | 'gemini', error: string): void {
278
- UIComponents.showErrorBox(`${service.toUpperCase()} API Error: ${error}`);
279
-
280
- console.log('\nTroubleshooting steps:');
281
-
282
- if (service === 'jules') {
283
- UIComponents.showList([
284
- 'Verify your Jules API key at https://jules.google.com',
285
- 'Check that the Jules GitHub app is installed on your repository',
286
- 'Ensure your API key has the required permissions',
287
- 'Try regenerating your API key if the issue persists'
288
- ]);
289
- } else {
290
- UIComponents.showList([
291
- 'Verify your Gemini API key at https://aistudio.google.com/app/apikey',
292
- 'Check that the Gemini API is enabled in your Google Cloud project',
293
- 'Ensure you have sufficient quota remaining',
294
- 'Try regenerating your API key if the issue persists'
295
- ]);
296
- }
297
- }
298
- }