baseguard 1.0.1 → 1.0.2

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 (151) hide show
  1. package/.baseguardrc.example.json +64 -0
  2. package/.eslintrc.json +1 -1
  3. package/CHANGELOG.md +196 -0
  4. package/DEPLOYMENT.md +625 -0
  5. package/DEPLOYMENT_CHECKLIST.md +239 -0
  6. package/DEPLOYMENT_SUMMARY_v1.0.2.md +202 -0
  7. package/QUICK_START.md +134 -0
  8. package/README.md +447 -52
  9. package/RELEASE_NOTES_v1.0.2.md +434 -0
  10. package/bin/base.js +64 -59
  11. package/dist/ai/agentkit-orchestrator.d.ts +116 -0
  12. package/dist/ai/agentkit-orchestrator.d.ts.map +1 -0
  13. package/dist/ai/agentkit-orchestrator.js +417 -0
  14. package/dist/ai/agentkit-orchestrator.js.map +1 -0
  15. package/dist/ai/gemini-code-fixer.d.ts +85 -0
  16. package/dist/ai/gemini-code-fixer.d.ts.map +1 -0
  17. package/dist/ai/gemini-code-fixer.js +452 -0
  18. package/dist/ai/gemini-code-fixer.js.map +1 -0
  19. package/dist/ai/jules-implementer.d.ts +5 -4
  20. package/dist/ai/jules-implementer.d.ts.map +1 -1
  21. package/dist/ai/jules-implementer.js +6 -5
  22. package/dist/ai/jules-implementer.js.map +1 -1
  23. package/dist/ai/unified-code-fixer.d.ts +69 -0
  24. package/dist/ai/unified-code-fixer.d.ts.map +1 -0
  25. package/dist/ai/unified-code-fixer.js +289 -0
  26. package/dist/ai/unified-code-fixer.js.map +1 -0
  27. package/dist/commands/check.d.ts +3 -1
  28. package/dist/commands/check.d.ts.map +1 -1
  29. package/dist/commands/check.js +166 -34
  30. package/dist/commands/check.js.map +1 -1
  31. package/dist/commands/config.d.ts +4 -0
  32. package/dist/commands/config.d.ts.map +1 -1
  33. package/dist/commands/config.js +183 -0
  34. package/dist/commands/config.js.map +1 -1
  35. package/dist/commands/fix.d.ts.map +1 -1
  36. package/dist/commands/fix.js +89 -91
  37. package/dist/commands/fix.js.map +1 -1
  38. package/dist/commands/index.d.ts +1 -0
  39. package/dist/commands/index.d.ts.map +1 -1
  40. package/dist/commands/index.js +1 -0
  41. package/dist/commands/index.js.map +1 -1
  42. package/dist/commands/init.d.ts.map +1 -1
  43. package/dist/commands/init.js +16 -2
  44. package/dist/commands/init.js.map +1 -1
  45. package/dist/commands/status.d.ts +14 -0
  46. package/dist/commands/status.d.ts.map +1 -0
  47. package/dist/commands/status.js +254 -0
  48. package/dist/commands/status.js.map +1 -0
  49. package/dist/core/baseguard.d.ts +47 -5
  50. package/dist/core/baseguard.d.ts.map +1 -1
  51. package/dist/core/baseguard.js +506 -52
  52. package/dist/core/baseguard.js.map +1 -1
  53. package/dist/core/cache-manager.d.ts.map +1 -1
  54. package/dist/core/cache-manager.js +3 -1
  55. package/dist/core/cache-manager.js.map +1 -1
  56. package/dist/core/configuration-recovery.d.ts +116 -0
  57. package/dist/core/configuration-recovery.d.ts.map +1 -0
  58. package/dist/core/configuration-recovery.js +552 -0
  59. package/dist/core/configuration-recovery.js.map +1 -0
  60. package/dist/core/configuration.d.ts +4 -0
  61. package/dist/core/configuration.d.ts.map +1 -1
  62. package/dist/core/configuration.js +35 -0
  63. package/dist/core/configuration.js.map +1 -1
  64. package/dist/core/debug-logger.d.ts +181 -0
  65. package/dist/core/debug-logger.d.ts.map +1 -0
  66. package/dist/core/debug-logger.js +479 -0
  67. package/dist/core/debug-logger.js.map +1 -0
  68. package/dist/core/file-processor.d.ts.map +1 -1
  69. package/dist/core/file-processor.js +8 -2
  70. package/dist/core/file-processor.js.map +1 -1
  71. package/dist/core/graceful-degradation-manager.d.ts +123 -0
  72. package/dist/core/graceful-degradation-manager.d.ts.map +1 -0
  73. package/dist/core/graceful-degradation-manager.js +512 -0
  74. package/dist/core/graceful-degradation-manager.js.map +1 -0
  75. package/dist/core/index.d.ts +4 -0
  76. package/dist/core/index.d.ts.map +1 -1
  77. package/dist/core/index.js +4 -0
  78. package/dist/core/index.js.map +1 -1
  79. package/dist/core/logger.d.ts +1 -0
  80. package/dist/core/logger.d.ts.map +1 -0
  81. package/dist/core/logger.js +2 -0
  82. package/dist/core/logger.js.map +1 -0
  83. package/dist/core/memory-manager.d.ts +84 -0
  84. package/dist/core/memory-manager.d.ts.map +1 -1
  85. package/dist/core/memory-manager.js +236 -1
  86. package/dist/core/memory-manager.js.map +1 -1
  87. package/dist/core/startup-optimizer.d.ts +12 -0
  88. package/dist/core/startup-optimizer.d.ts.map +1 -1
  89. package/dist/core/startup-optimizer.js +60 -0
  90. package/dist/core/startup-optimizer.js.map +1 -1
  91. package/dist/core/system-error-handler.d.ts +65 -0
  92. package/dist/core/system-error-handler.d.ts.map +1 -0
  93. package/dist/core/system-error-handler.js +646 -0
  94. package/dist/core/system-error-handler.js.map +1 -0
  95. package/dist/git/github-manager.d.ts +5 -16
  96. package/dist/git/github-manager.d.ts.map +1 -1
  97. package/dist/git/github-manager.js +6 -61
  98. package/dist/git/github-manager.js.map +1 -1
  99. package/dist/parsers/react-parser-optimized.d.ts +16 -0
  100. package/dist/parsers/react-parser-optimized.d.ts.map +1 -0
  101. package/dist/parsers/react-parser-optimized.js +147 -0
  102. package/dist/parsers/react-parser-optimized.js.map +1 -0
  103. package/dist/parsers/react-parser.d.ts.map +1 -1
  104. package/dist/parsers/react-parser.js +17 -15
  105. package/dist/parsers/react-parser.js.map +1 -1
  106. package/dist/parsers/svelte-parser.d.ts.map +1 -1
  107. package/dist/parsers/svelte-parser.js +7 -3
  108. package/dist/parsers/svelte-parser.js.map +1 -1
  109. package/dist/parsers/vanilla-parser.d.ts.map +1 -1
  110. package/dist/parsers/vanilla-parser.js +7 -3
  111. package/dist/parsers/vanilla-parser.js.map +1 -1
  112. package/dist/parsers/vue-parser.d.ts +18 -0
  113. package/dist/parsers/vue-parser.d.ts.map +1 -1
  114. package/dist/parsers/vue-parser.js +387 -1
  115. package/dist/parsers/vue-parser.js.map +1 -1
  116. package/dist/types/index.d.ts +4 -0
  117. package/dist/types/index.d.ts.map +1 -1
  118. package/dist/ui/help.js +1 -1
  119. package/dist/ui/help.js.map +1 -1
  120. package/dist/ui/prompts.d.ts +7 -4
  121. package/dist/ui/prompts.d.ts.map +1 -1
  122. package/dist/ui/prompts.js +48 -55
  123. package/dist/ui/prompts.js.map +1 -1
  124. package/package.json +31 -6
  125. package/src/ai/__tests__/gemini-analyzer.test.ts +2 -2
  126. package/src/ai/agentkit-orchestrator.ts +534 -0
  127. package/src/ai/gemini-code-fixer.ts +540 -0
  128. package/src/ai/jules-implementer.ts +6 -5
  129. package/src/ai/unified-code-fixer.ts +347 -0
  130. package/src/commands/config.ts +126 -0
  131. package/src/commands/fix.ts +98 -94
  132. package/src/commands/init.ts +16 -2
  133. package/src/core/cache-manager.ts +4 -2
  134. package/src/core/configuration.ts +37 -0
  135. package/src/core/debug-logger.ts +2 -2
  136. package/src/core/file-processor.ts +10 -3
  137. package/src/core/index.ts +5 -1
  138. package/src/core/memory-manager.ts +4 -3
  139. package/src/core/startup-optimizer.ts +70 -0
  140. package/src/git/github-manager.ts +11 -79
  141. package/src/parsers/react-parser.ts +2 -2
  142. package/src/parsers/svelte-parser.ts +13 -9
  143. package/src/parsers/vanilla-parser.ts +18 -14
  144. package/src/parsers/vue-parser.ts +20 -14
  145. package/src/types/index.ts +4 -0
  146. package/src/ui/help.ts +1 -1
  147. package/src/ui/prompts.ts +54 -61
  148. package/test-build.js +41 -0
  149. package/tests/e2e/git-integration.e2e.test.ts +1 -1
  150. package/tsconfig.json +0 -1
  151. package/vitest.config.ts +4 -2
@@ -0,0 +1,540 @@
1
+ import type { Violation, Analysis, Fix } from '../types/index.js';
2
+ import { promises as fs } from 'fs';
3
+ import { ErrorHandler, APIError, ErrorType } from '../core/error-handler.js';
4
+ import { logger } from '../core/debug-logger.js';
5
+ import chalk from 'chalk';
6
+
7
+ /**
8
+ * Gemini 2.5 Pro code fixer for local files and repositories
9
+ * Works with any code (GitHub or not, committed or uncommitted)
10
+ */
11
+ export class GeminiCodeFixer {
12
+ private apiKey: string;
13
+ private baseUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent';
14
+ private categoryLogger: ReturnType<typeof logger.createCategoryLogger>;
15
+
16
+ constructor(apiKey: string) {
17
+ this.apiKey = apiKey;
18
+ this.categoryLogger = logger.createCategoryLogger('gemini-code-fixer');
19
+ }
20
+
21
+ /**
22
+ * Generate a fix using Gemini 2.5 Pro with grounding
23
+ */
24
+ async generateFix(violation: Violation, analysis: Analysis): Promise<Fix> {
25
+ const context = ErrorHandler.createContext('gemini_code_fix', {
26
+ feature: violation.feature,
27
+ file: violation.file,
28
+ browser: violation.browser
29
+ });
30
+
31
+ try {
32
+ this.categoryLogger.info('Generating code fix', {
33
+ feature: violation.feature,
34
+ file: violation.file,
35
+ strategy: analysis.fixStrategy
36
+ });
37
+
38
+ // Read the current file content
39
+ const fileContent = await this.readFileContent(violation.file);
40
+
41
+ // Build the fix prompt with file context
42
+ const prompt = this.buildFixPrompt(violation, analysis, fileContent);
43
+
44
+ const response = await ErrorHandler.withRetry(
45
+ () => this.makeApiCall(prompt),
46
+ {
47
+ maxRetries: 2,
48
+ retryableErrors: [ErrorType.NETWORK, ErrorType.TIMEOUT, ErrorType.RATE_LIMIT, ErrorType.SERVER_ERROR]
49
+ }
50
+ );
51
+
52
+ const data = await response.json();
53
+
54
+ // Validate response structure
55
+ ErrorHandler.validateAPIResponse(data, ['candidates']);
56
+
57
+ if (!data.candidates || data.candidates.length === 0) {
58
+ throw new APIError(
59
+ 'No fix candidates returned from Gemini API',
60
+ ErrorType.VALIDATION,
61
+ {
62
+ suggestions: [
63
+ 'Try rephrasing the fix request',
64
+ 'Check if the code is valid',
65
+ 'Try again with a different approach'
66
+ ],
67
+ context
68
+ }
69
+ );
70
+ }
71
+
72
+ const candidate = data.candidates[0];
73
+ const content = candidate.content?.parts?.[0]?.text;
74
+
75
+ if (!content) {
76
+ throw new APIError(
77
+ 'Empty fix content returned from Gemini API',
78
+ ErrorType.VALIDATION,
79
+ {
80
+ suggestions: [
81
+ 'Try the fix generation again',
82
+ 'Check if the violation data is complete',
83
+ 'Verify API key permissions'
84
+ ],
85
+ context
86
+ }
87
+ );
88
+ }
89
+
90
+ // Parse the fix response and generate proper diff
91
+ const fix = await this.parseFixResponse(content, violation, analysis, fileContent);
92
+
93
+ this.categoryLogger.info('Code fix generated successfully', {
94
+ feature: violation.feature,
95
+ confidence: fix.confidence,
96
+ hasPreview: fix.preview.length > 0
97
+ });
98
+
99
+ return fix;
100
+
101
+ } catch (error) {
102
+ const apiError = ErrorHandler.handleAPIError(error, context);
103
+ this.categoryLogger.error('Code fix generation failed', { error: apiError });
104
+ throw apiError;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Make API call to Gemini 2.5 Pro with grounding
110
+ */
111
+ private async makeApiCall(prompt: string): Promise<Response> {
112
+ const response = await fetch(this.baseUrl, {
113
+ method: 'POST',
114
+ headers: {
115
+ 'x-goog-api-key': this.apiKey,
116
+ 'Content-Type': 'application/json'
117
+ },
118
+ body: JSON.stringify({
119
+ contents: [{
120
+ parts: [{ text: prompt }]
121
+ }],
122
+ tools: [{
123
+ googleSearchRetrieval: {
124
+ dynamicRetrievalConfig: {
125
+ mode: 'MODE_DYNAMIC',
126
+ dynamicThreshold: 0.7
127
+ }
128
+ }
129
+ }],
130
+ generationConfig: {
131
+ temperature: 0.1,
132
+ topK: 40,
133
+ topP: 0.95,
134
+ maxOutputTokens: 4096,
135
+ candidateCount: 1
136
+ }
137
+ })
138
+ });
139
+
140
+ if (!response.ok) {
141
+ const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
142
+ (error as any).response = response;
143
+ throw error;
144
+ }
145
+
146
+ return response;
147
+ }
148
+
149
+ /**
150
+ * Build comprehensive fix prompt for Gemini 2.5 Pro
151
+ */
152
+ private buildFixPrompt(violation: Violation, analysis: Analysis, fileContent: string): string {
153
+ return `You are an expert web developer tasked with fixing browser compatibility issues. Generate a precise code fix with proper diff format.
154
+
155
+ ## COMPATIBILITY ISSUE
156
+ - **Feature**: ${violation.feature}
157
+ - **File**: ${violation.file} (line ${violation.line})
158
+ - **Unsupported Browser**: ${violation.browser} ${violation.required}
159
+ - **Baseline Status**: ${violation.baselineStatus}
160
+ - **Current Code Context**: ${violation.context}
161
+
162
+ ## ANALYSIS INSIGHTS
163
+ - **Fix Strategy**: ${analysis.fixStrategy}
164
+ - **User Impact**: ${analysis.userImpact}
165
+ - **Market Share Affected**: ${(analysis.marketShare * 100).toFixed(1)}%
166
+ - **Best Practices**: ${analysis.bestPractices.join(', ')}
167
+
168
+ ## CURRENT FILE CONTENT
169
+ \`\`\`${this.getFileExtension(violation.file)}
170
+ ${fileContent}
171
+ \`\`\`
172
+
173
+ ## REQUIREMENTS
174
+ 1. **Fix the compatibility issue** using ${analysis.fixStrategy}
175
+ 2. **Preserve all existing functionality** - no breaking changes
176
+ 3. **Add proper fallbacks** for ${violation.browser} ${violation.required}
177
+ 4. **Follow best practices**: ${analysis.bestPractices.join(', ')}
178
+ 5. **Generate a unified diff** showing exactly what changes to make
179
+ 6. **Provide clear explanation** of the fix approach
180
+
181
+ ## OUTPUT FORMAT
182
+ Please provide your response in this exact format:
183
+
184
+ ### EXPLANATION
185
+ [Explain the fix approach and why it works]
186
+
187
+ ### DIFF
188
+ \`\`\`diff
189
+ --- a/${violation.file}
190
+ +++ b/${violation.file}
191
+ @@ -[start_line],[num_lines] +[start_line],[num_lines] @@
192
+ [unified diff content showing the exact changes]
193
+ \`\`\`
194
+
195
+ ### PREVIEW
196
+ \`\`\`${this.getFileExtension(violation.file)}
197
+ [Show the key changed sections with context]
198
+ \`\`\`
199
+
200
+ ### TESTING
201
+ [Suggest how to test the fix works in ${violation.browser} ${violation.required}]
202
+
203
+ Focus on creating a production-ready fix that maintains compatibility across all browsers while adding proper support for ${violation.browser} ${violation.required}.`;
204
+ }
205
+
206
+ /**
207
+ * Read file content with error handling
208
+ */
209
+ private async readFileContent(filePath: string): Promise<string> {
210
+ try {
211
+ return await fs.readFile(filePath, 'utf-8');
212
+ } catch (error) {
213
+ this.categoryLogger.warn('Could not read file content', {
214
+ file: filePath,
215
+ error: error instanceof Error ? error.message : 'Unknown error'
216
+ });
217
+
218
+ // Return empty content if file can't be read
219
+ return `// File content could not be read: ${filePath}`;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Get file extension for syntax highlighting
225
+ */
226
+ private getFileExtension(filePath: string): string {
227
+ const ext = filePath.split('.').pop()?.toLowerCase();
228
+
229
+ const extensionMap: Record<string, string> = {
230
+ 'js': 'javascript',
231
+ 'jsx': 'javascript',
232
+ 'ts': 'typescript',
233
+ 'tsx': 'typescript',
234
+ 'vue': 'vue',
235
+ 'svelte': 'svelte',
236
+ 'css': 'css',
237
+ 'scss': 'scss',
238
+ 'sass': 'sass',
239
+ 'html': 'html',
240
+ 'htm': 'html'
241
+ };
242
+
243
+ return extensionMap[ext || ''] || 'text';
244
+ }
245
+
246
+ /**
247
+ * Parse Gemini's fix response and create Fix object
248
+ */
249
+ private async parseFixResponse(
250
+ content: string,
251
+ violation: Violation,
252
+ analysis: Analysis,
253
+ originalContent: string
254
+ ): Promise<Fix> {
255
+ try {
256
+ // Extract sections from the response
257
+ const explanation = this.extractSection(content, 'EXPLANATION');
258
+ const diffContent = this.extractSection(content, 'DIFF');
259
+ const preview = this.extractSection(content, 'PREVIEW');
260
+ const testing = this.extractSection(content, 'TESTING');
261
+
262
+ // Clean up the diff content
263
+ const cleanDiff = this.cleanDiffContent(diffContent);
264
+
265
+ // Generate a human-readable preview if not provided
266
+ const finalPreview = preview || this.generatePreviewFromDiff(cleanDiff, originalContent);
267
+
268
+ // Calculate confidence based on response quality
269
+ const confidence = this.calculateFixConfidence(content, diffContent);
270
+
271
+ // Create comprehensive explanation
272
+ const fullExplanation = this.buildFullExplanation(
273
+ violation,
274
+ analysis,
275
+ explanation,
276
+ testing
277
+ );
278
+
279
+ return {
280
+ violation,
281
+ analysis,
282
+ patch: cleanDiff,
283
+ explanation: fullExplanation,
284
+ filePath: violation.file,
285
+ preview: finalPreview,
286
+ confidence,
287
+ testable: true
288
+ };
289
+
290
+ } catch (error) {
291
+ this.categoryLogger.error('Failed to parse fix response', { error });
292
+
293
+ // Return a basic fix with the raw content
294
+ return {
295
+ violation,
296
+ analysis,
297
+ patch: this.generateBasicDiff(violation.file, content),
298
+ explanation: `Fix generated for ${violation.feature} compatibility issue.\n\n${content}`,
299
+ filePath: violation.file,
300
+ preview: content.substring(0, 500) + (content.length > 500 ? '...' : ''),
301
+ confidence: 0.6,
302
+ testable: true
303
+ };
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Extract a specific section from the response
309
+ */
310
+ private extractSection(content: string, sectionName: string): string {
311
+ const regex = new RegExp(`### ${sectionName}\\s*\\n([\\s\\S]*?)(?=\\n### |$)`, 'i');
312
+ const match = content.match(regex);
313
+
314
+ if (match && match[1]) {
315
+ return match[1].trim();
316
+ }
317
+
318
+ return '';
319
+ }
320
+
321
+ /**
322
+ * Clean and validate diff content
323
+ */
324
+ private cleanDiffContent(diffContent: string): string {
325
+ if (!diffContent) {
326
+ return '';
327
+ }
328
+
329
+ // Remove code block markers if present
330
+ let cleaned = diffContent.replace(/^```diff\\n|```$/gm, '').trim();
331
+
332
+ // Ensure it starts with proper diff headers
333
+ if (!cleaned.startsWith('---') && !cleaned.startsWith('@@')) {
334
+ // If it's just the diff content without headers, add basic headers
335
+ cleaned = `--- a/file\n+++ b/file\n${cleaned}`;
336
+ }
337
+
338
+ return cleaned;
339
+ }
340
+
341
+ /**
342
+ * Generate preview from diff content
343
+ */
344
+ private generatePreviewFromDiff(diffContent: string, originalContent: string): string {
345
+ if (!diffContent) {
346
+ return 'No preview available';
347
+ }
348
+
349
+ try {
350
+ // Extract added lines from diff
351
+ const addedLines = diffContent
352
+ .split('\n')
353
+ .filter(line => line.startsWith('+') && !line.startsWith('+++'))
354
+ .map(line => line.substring(1))
355
+ .join('\n');
356
+
357
+ if (addedLines) {
358
+ return `Changes to be applied:\n\n${addedLines}`;
359
+ }
360
+ } catch (error) {
361
+ // Fallback to showing first part of diff
362
+ }
363
+
364
+ return diffContent.substring(0, 300) + (diffContent.length > 300 ? '...' : '');
365
+ }
366
+
367
+ /**
368
+ * Calculate confidence score based on response quality
369
+ */
370
+ private calculateFixConfidence(content: string, diffContent: string): number {
371
+ let confidence = 0.5; // Base confidence
372
+
373
+ // Check if response has proper structure
374
+ if (content.includes('### EXPLANATION')) confidence += 0.1;
375
+ if (content.includes('### DIFF')) confidence += 0.1;
376
+ if (content.includes('### PREVIEW')) confidence += 0.1;
377
+ if (content.includes('### TESTING')) confidence += 0.1;
378
+
379
+ // Check diff quality
380
+ if (diffContent && diffContent.includes('@@')) confidence += 0.1;
381
+ if (diffContent && (diffContent.includes('+') || diffContent.includes('-'))) confidence += 0.1;
382
+
383
+ return Math.min(confidence, 0.9); // Cap at 0.9
384
+ }
385
+
386
+ /**
387
+ * Build comprehensive explanation
388
+ */
389
+ private buildFullExplanation(
390
+ violation: Violation,
391
+ analysis: Analysis,
392
+ explanation: string,
393
+ testing: string
394
+ ): string {
395
+ let fullExplanation = `Fixed ${violation.feature} compatibility issue in ${violation.file}\n\n`;
396
+
397
+ if (explanation) {
398
+ fullExplanation += `## Fix Approach\n${explanation}\n\n`;
399
+ }
400
+
401
+ fullExplanation += `## Strategy Applied\n${analysis.fixStrategy}\n\n`;
402
+ fullExplanation += `## Browser Support\nThis fix ensures compatibility with ${violation.browser} ${violation.required} and newer versions.\n\n`;
403
+
404
+ if (testing) {
405
+ fullExplanation += `## Testing\n${testing}\n\n`;
406
+ }
407
+
408
+ fullExplanation += `## Best Practices Applied\n${analysis.bestPractices.map(practice => `• ${practice}`).join('\n')}`;
409
+
410
+ return fullExplanation;
411
+ }
412
+
413
+ /**
414
+ * Generate basic diff as fallback
415
+ */
416
+ private generateBasicDiff(filePath: string, content: string): string {
417
+ return `--- a/${filePath}
418
+ +++ b/${filePath}
419
+ @@ -1,1 +1,1 @@
420
+ -// Original code (manual review required)
421
+ +// Fixed code: ${content.substring(0, 100)}${content.length > 100 ? '...' : ''}
422
+
423
+ # Manual fix required - please review the generated content above
424
+ # and apply the appropriate changes to your code.`;
425
+ }
426
+
427
+ /**
428
+ * Test API connectivity
429
+ */
430
+ async testConnection(): Promise<{ success: boolean; error?: string; errorType?: ErrorType }> {
431
+ try {
432
+ const testPrompt = 'Generate a simple "Hello, World!" comment in JavaScript.';
433
+ const response = await this.makeApiCall(testPrompt);
434
+
435
+ const data = await response.json();
436
+
437
+ if (data.candidates && data.candidates.length > 0) {
438
+ return { success: true };
439
+ } else {
440
+ return {
441
+ success: false,
442
+ error: 'API responded but returned no content',
443
+ errorType: ErrorType.VALIDATION
444
+ };
445
+ }
446
+ } catch (error) {
447
+ const apiError = ErrorHandler.handleAPIError(error);
448
+
449
+ return {
450
+ success: false,
451
+ error: apiError.message,
452
+ errorType: apiError.type
453
+ };
454
+ }
455
+ }
456
+
457
+ /**
458
+ * Validate API key format
459
+ */
460
+ public static validateApiKey(apiKey: string): boolean {
461
+ // Gemini API keys typically start with 'AIza' and are 39+ characters long
462
+ return /^AIza[A-Za-z0-9_-]{35,}$/.test(apiKey) || apiKey.length >= 20;
463
+ }
464
+
465
+ /**
466
+ * Generate multiple fix options for complex issues
467
+ */
468
+ async generateFixOptions(violation: Violation, analysis: Analysis): Promise<Fix[]> {
469
+ const fixes: Fix[] = [];
470
+
471
+ try {
472
+ // Generate primary fix
473
+ const primaryFix = await this.generateFix(violation, analysis);
474
+ fixes.push(primaryFix);
475
+
476
+ // Generate alternative approaches if confidence is low
477
+ if (primaryFix.confidence < 0.7) {
478
+ this.categoryLogger.info('Generating alternative fix approaches', {
479
+ feature: violation.feature,
480
+ primaryConfidence: primaryFix.confidence
481
+ });
482
+
483
+ const alternativeFix = await this.generateAlternativeFix(violation, analysis);
484
+ if (alternativeFix) {
485
+ fixes.push(alternativeFix);
486
+ }
487
+ }
488
+
489
+ } catch (error) {
490
+ this.categoryLogger.error('Failed to generate fix options', { error });
491
+ throw error;
492
+ }
493
+
494
+ return fixes;
495
+ }
496
+
497
+ /**
498
+ * Generate alternative fix approach
499
+ */
500
+ private async generateAlternativeFix(violation: Violation, analysis: Analysis): Promise<Fix | null> {
501
+ try {
502
+ const fileContent = await this.readFileContent(violation.file);
503
+
504
+ // Build alternative prompt with different strategy
505
+ const alternativePrompt = this.buildAlternativeFixPrompt(violation, analysis, fileContent);
506
+
507
+ const response = await this.makeApiCall(alternativePrompt);
508
+ const data = await response.json();
509
+
510
+ if (data.candidates && data.candidates.length > 0) {
511
+ const content = data.candidates[0].content?.parts?.[0]?.text;
512
+ if (content) {
513
+ const fix = await this.parseFixResponse(content, violation, analysis, fileContent);
514
+ fix.explanation = `Alternative approach: ${fix.explanation}`;
515
+ return fix;
516
+ }
517
+ }
518
+
519
+ } catch (error) {
520
+ this.categoryLogger.warn('Failed to generate alternative fix', { error });
521
+ }
522
+
523
+ return null;
524
+ }
525
+
526
+ /**
527
+ * Build alternative fix prompt with different strategy
528
+ */
529
+ private buildAlternativeFixPrompt(violation: Violation, analysis: Analysis, fileContent: string): string {
530
+ const alternativeStrategies = {
531
+ 'progressive enhancement with @supports': 'feature detection with JavaScript',
532
+ 'feature detection with polyfills': 'progressive enhancement with @supports',
533
+ 'graceful degradation': 'polyfill-based approach'
534
+ };
535
+
536
+ const altStrategy = alternativeStrategies[analysis.fixStrategy as keyof typeof alternativeStrategies] || 'alternative progressive enhancement';
537
+
538
+ return this.buildFixPrompt(violation, { ...analysis, fixStrategy: altStrategy }, fileContent);
539
+ }
540
+ }
@@ -6,6 +6,7 @@ import chalk from 'chalk';
6
6
 
7
7
  /**
8
8
  * Jules AI implementer for autonomous code fixing
9
+ * Note: Jules requires GitHub repositories and cannot work with local files
9
10
  */
10
11
  export class JulesImplementer {
11
12
  private apiKey: string;
@@ -354,16 +355,16 @@ Please fix this compatibility issue while maintaining the existing functionality
354
355
  }
355
356
 
356
357
  /**
357
- * Setup Jules GitHub integration
358
+ * Get repository source identifier (GitHub integration is handled on Jules dashboard)
358
359
  */
359
- async setupGitHubIntegration(): Promise<string> {
360
- return await this.githubManager.setupJulesGitHubIntegration();
360
+ async getRepositorySource(): Promise<string> {
361
+ return await this.githubManager.getSourceIdentifier();
361
362
  }
362
363
 
363
364
  /**
364
- * Check if GitHub integration is set up
365
+ * Check if repository information is available (GitHub integration is handled on Jules dashboard)
365
366
  */
366
- async isGitHubIntegrationSetup(): Promise<boolean> {
367
+ async isRepositoryDetected(): Promise<boolean> {
367
368
  return await this.githubManager.isJulesIntegrationSetup();
368
369
  }
369
370