baseguard 1.0.0

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 (244) hide show
  1. package/.eslintrc.json +25 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +94 -0
  4. package/bin/base.js +494 -0
  5. package/dist/ai/fix-manager.d.ts +67 -0
  6. package/dist/ai/fix-manager.d.ts.map +1 -0
  7. package/dist/ai/fix-manager.js +326 -0
  8. package/dist/ai/fix-manager.js.map +1 -0
  9. package/dist/ai/gemini-analyzer.d.ts +116 -0
  10. package/dist/ai/gemini-analyzer.d.ts.map +1 -0
  11. package/dist/ai/gemini-analyzer.js +572 -0
  12. package/dist/ai/gemini-analyzer.js.map +1 -0
  13. package/dist/ai/index.d.ts +4 -0
  14. package/dist/ai/index.d.ts.map +1 -0
  15. package/dist/ai/index.js +5 -0
  16. package/dist/ai/index.js.map +1 -0
  17. package/dist/ai/jules-implementer.d.ts +115 -0
  18. package/dist/ai/jules-implementer.d.ts.map +1 -0
  19. package/dist/ai/jules-implementer.js +387 -0
  20. package/dist/ai/jules-implementer.js.map +1 -0
  21. package/dist/commands/automation.d.ts +5 -0
  22. package/dist/commands/automation.d.ts.map +1 -0
  23. package/dist/commands/automation.js +305 -0
  24. package/dist/commands/automation.js.map +1 -0
  25. package/dist/commands/check.d.ts +9 -0
  26. package/dist/commands/check.d.ts.map +1 -0
  27. package/dist/commands/check.js +113 -0
  28. package/dist/commands/check.js.map +1 -0
  29. package/dist/commands/config.d.ts +11 -0
  30. package/dist/commands/config.d.ts.map +1 -0
  31. package/dist/commands/config.js +324 -0
  32. package/dist/commands/config.js.map +1 -0
  33. package/dist/commands/fix.d.ts +9 -0
  34. package/dist/commands/fix.d.ts.map +1 -0
  35. package/dist/commands/fix.js +207 -0
  36. package/dist/commands/fix.js.map +1 -0
  37. package/dist/commands/index.d.ts +6 -0
  38. package/dist/commands/index.d.ts.map +1 -0
  39. package/dist/commands/index.js +7 -0
  40. package/dist/commands/index.js.map +1 -0
  41. package/dist/commands/init.d.ts +9 -0
  42. package/dist/commands/init.d.ts.map +1 -0
  43. package/dist/commands/init.js +125 -0
  44. package/dist/commands/init.js.map +1 -0
  45. package/dist/core/api-key-manager.d.ts +83 -0
  46. package/dist/core/api-key-manager.d.ts.map +1 -0
  47. package/dist/core/api-key-manager.js +244 -0
  48. package/dist/core/api-key-manager.js.map +1 -0
  49. package/dist/core/baseguard.d.ts +46 -0
  50. package/dist/core/baseguard.d.ts.map +1 -0
  51. package/dist/core/baseguard.js +132 -0
  52. package/dist/core/baseguard.js.map +1 -0
  53. package/dist/core/baseline-checker.d.ts +63 -0
  54. package/dist/core/baseline-checker.d.ts.map +1 -0
  55. package/dist/core/baseline-checker.js +502 -0
  56. package/dist/core/baseline-checker.js.map +1 -0
  57. package/dist/core/cache-manager.d.ts +88 -0
  58. package/dist/core/cache-manager.d.ts.map +1 -0
  59. package/dist/core/cache-manager.js +213 -0
  60. package/dist/core/cache-manager.js.map +1 -0
  61. package/dist/core/configuration.d.ts +140 -0
  62. package/dist/core/configuration.d.ts.map +1 -0
  63. package/dist/core/configuration.js +474 -0
  64. package/dist/core/configuration.js.map +1 -0
  65. package/dist/core/directory-filter.d.ts +90 -0
  66. package/dist/core/directory-filter.d.ts.map +1 -0
  67. package/dist/core/directory-filter.js +319 -0
  68. package/dist/core/directory-filter.js.map +1 -0
  69. package/dist/core/error-handler.d.ts +110 -0
  70. package/dist/core/error-handler.d.ts.map +1 -0
  71. package/dist/core/error-handler.js +392 -0
  72. package/dist/core/error-handler.js.map +1 -0
  73. package/dist/core/file-processor.d.ts +80 -0
  74. package/dist/core/file-processor.d.ts.map +1 -0
  75. package/dist/core/file-processor.js +259 -0
  76. package/dist/core/file-processor.js.map +1 -0
  77. package/dist/core/gitignore-manager.d.ts +44 -0
  78. package/dist/core/gitignore-manager.d.ts.map +1 -0
  79. package/dist/core/gitignore-manager.js +147 -0
  80. package/dist/core/gitignore-manager.js.map +1 -0
  81. package/dist/core/index.d.ts +13 -0
  82. package/dist/core/index.d.ts.map +1 -0
  83. package/dist/core/index.js +13 -0
  84. package/dist/core/index.js.map +1 -0
  85. package/dist/core/lazy-loader.d.ts +68 -0
  86. package/dist/core/lazy-loader.d.ts.map +1 -0
  87. package/dist/core/lazy-loader.js +260 -0
  88. package/dist/core/lazy-loader.js.map +1 -0
  89. package/dist/core/memory-manager.d.ts +1 -0
  90. package/dist/core/memory-manager.d.ts.map +1 -0
  91. package/dist/core/memory-manager.js +2 -0
  92. package/dist/core/memory-manager.js.map +1 -0
  93. package/dist/core/startup-optimizer.d.ts +45 -0
  94. package/dist/core/startup-optimizer.d.ts.map +1 -0
  95. package/dist/core/startup-optimizer.js +140 -0
  96. package/dist/core/startup-optimizer.js.map +1 -0
  97. package/dist/git/automation-engine.d.ts +58 -0
  98. package/dist/git/automation-engine.d.ts.map +1 -0
  99. package/dist/git/automation-engine.js +318 -0
  100. package/dist/git/automation-engine.js.map +1 -0
  101. package/dist/git/github-manager.d.ts +71 -0
  102. package/dist/git/github-manager.d.ts.map +1 -0
  103. package/dist/git/github-manager.js +226 -0
  104. package/dist/git/github-manager.js.map +1 -0
  105. package/dist/git/hook-manager.d.ts +43 -0
  106. package/dist/git/hook-manager.d.ts.map +1 -0
  107. package/dist/git/hook-manager.js +191 -0
  108. package/dist/git/hook-manager.js.map +1 -0
  109. package/dist/git/index.d.ts +4 -0
  110. package/dist/git/index.d.ts.map +1 -0
  111. package/dist/git/index.js +5 -0
  112. package/dist/git/index.js.map +1 -0
  113. package/dist/index.d.ts +8 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +9 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/parsers/feature-validator.d.ts +60 -0
  118. package/dist/parsers/feature-validator.d.ts.map +1 -0
  119. package/dist/parsers/feature-validator.js +483 -0
  120. package/dist/parsers/feature-validator.js.map +1 -0
  121. package/dist/parsers/index.d.ts +8 -0
  122. package/dist/parsers/index.d.ts.map +1 -0
  123. package/dist/parsers/index.js +9 -0
  124. package/dist/parsers/index.js.map +1 -0
  125. package/dist/parsers/parser-manager.d.ts +103 -0
  126. package/dist/parsers/parser-manager.d.ts.map +1 -0
  127. package/dist/parsers/parser-manager.js +321 -0
  128. package/dist/parsers/parser-manager.js.map +1 -0
  129. package/dist/parsers/parser.d.ts +23 -0
  130. package/dist/parsers/parser.d.ts.map +1 -0
  131. package/dist/parsers/parser.js +6 -0
  132. package/dist/parsers/parser.js.map +1 -0
  133. package/dist/parsers/react-parser.d.ts +22 -0
  134. package/dist/parsers/react-parser.d.ts.map +1 -0
  135. package/dist/parsers/react-parser.js +307 -0
  136. package/dist/parsers/react-parser.js.map +1 -0
  137. package/dist/parsers/svelte-parser.d.ts +33 -0
  138. package/dist/parsers/svelte-parser.d.ts.map +1 -0
  139. package/dist/parsers/svelte-parser.js +408 -0
  140. package/dist/parsers/svelte-parser.js.map +1 -0
  141. package/dist/parsers/vanilla-parser.d.ts +31 -0
  142. package/dist/parsers/vanilla-parser.d.ts.map +1 -0
  143. package/dist/parsers/vanilla-parser.js +590 -0
  144. package/dist/parsers/vanilla-parser.js.map +1 -0
  145. package/dist/parsers/vue-parser.d.ts +9 -0
  146. package/dist/parsers/vue-parser.d.ts.map +1 -0
  147. package/dist/parsers/vue-parser.js +16 -0
  148. package/dist/parsers/vue-parser.js.map +1 -0
  149. package/dist/terminal-header.d.ts +12 -0
  150. package/dist/terminal-header.js +45 -0
  151. package/dist/types/index.d.ts +83 -0
  152. package/dist/types/index.d.ts.map +1 -0
  153. package/dist/types/index.js +5 -0
  154. package/dist/types/index.js.map +1 -0
  155. package/dist/ui/components.d.ts +133 -0
  156. package/dist/ui/components.d.ts.map +1 -0
  157. package/dist/ui/components.js +482 -0
  158. package/dist/ui/components.js.map +1 -0
  159. package/dist/ui/help.d.ts +11 -0
  160. package/dist/ui/help.d.ts.map +1 -0
  161. package/dist/ui/help.js +161 -0
  162. package/dist/ui/help.js.map +1 -0
  163. package/dist/ui/index.d.ts +5 -0
  164. package/dist/ui/index.d.ts.map +1 -0
  165. package/dist/ui/index.js +5 -0
  166. package/dist/ui/index.js.map +1 -0
  167. package/dist/ui/prompts.d.ts +63 -0
  168. package/dist/ui/prompts.d.ts.map +1 -0
  169. package/dist/ui/prompts.js +611 -0
  170. package/dist/ui/prompts.js.map +1 -0
  171. package/dist/ui/terminal-header.d.ts +13 -0
  172. package/dist/ui/terminal-header.d.ts.map +1 -0
  173. package/dist/ui/terminal-header.js +46 -0
  174. package/dist/ui/terminal-header.js.map +1 -0
  175. package/package.json +80 -0
  176. package/src/ai/__tests__/gemini-analyzer.test.ts +181 -0
  177. package/src/ai/fix-manager.ts +362 -0
  178. package/src/ai/gemini-analyzer.ts +671 -0
  179. package/src/ai/index.ts +4 -0
  180. package/src/ai/jules-implementer.ts +459 -0
  181. package/src/commands/automation.ts +344 -0
  182. package/src/commands/check.ts +299 -0
  183. package/src/commands/config.ts +365 -0
  184. package/src/commands/fix.ts +234 -0
  185. package/src/commands/index.ts +6 -0
  186. package/src/commands/init.ts +142 -0
  187. package/src/commands/status.ts +0 -0
  188. package/src/core/api-key-manager.ts +298 -0
  189. package/src/core/baseguard.ts +742 -0
  190. package/src/core/baseline-checker.ts +563 -0
  191. package/src/core/cache-manager.ts +270 -0
  192. package/src/core/configuration-recovery.ts +676 -0
  193. package/src/core/configuration.ts +559 -0
  194. package/src/core/debug-logger.ts +590 -0
  195. package/src/core/directory-filter.ts +421 -0
  196. package/src/core/error-handler.ts +517 -0
  197. package/src/core/file-processor.ts +331 -0
  198. package/src/core/gitignore-manager.ts +169 -0
  199. package/src/core/graceful-degradation-manager.ts +596 -0
  200. package/src/core/index.ts +13 -0
  201. package/src/core/lazy-loader.ts +307 -0
  202. package/src/core/logger.ts +0 -0
  203. package/src/core/memory-manager.ts +294 -0
  204. package/src/core/startup-optimizer.ts +173 -0
  205. package/src/core/system-error-handler.ts +746 -0
  206. package/src/git/automation-engine.ts +361 -0
  207. package/src/git/github-manager.ts +260 -0
  208. package/src/git/hook-manager.ts +210 -0
  209. package/src/git/index.ts +4 -0
  210. package/src/index.ts +8 -0
  211. package/src/parsers/feature-validator.ts +559 -0
  212. package/src/parsers/index.ts +8 -0
  213. package/src/parsers/parser-manager.ts +419 -0
  214. package/src/parsers/parser.ts +26 -0
  215. package/src/parsers/react-parser-optimized.ts +161 -0
  216. package/src/parsers/react-parser.ts +359 -0
  217. package/src/parsers/svelte-parser.ts +506 -0
  218. package/src/parsers/vanilla-parser.ts +682 -0
  219. package/src/parsers/vue-parser.ts +472 -0
  220. package/src/types/index.ts +92 -0
  221. package/src/ui/components.ts +567 -0
  222. package/src/ui/help.ts +193 -0
  223. package/src/ui/index.ts +4 -0
  224. package/src/ui/prompts.ts +688 -0
  225. package/src/ui/terminal-header.ts +59 -0
  226. package/test-config-commands.js +56 -0
  227. package/test-header-simple.js +33 -0
  228. package/test-terminal-header.js +12 -0
  229. package/test-ui.js +29 -0
  230. package/tests/e2e/baseguard.e2e.test.ts +516 -0
  231. package/tests/e2e/cross-platform.e2e.test.ts +420 -0
  232. package/tests/e2e/git-integration.e2e.test.ts +487 -0
  233. package/tests/fixtures/react-project/package.json +14 -0
  234. package/tests/fixtures/react-project/src/App.css +76 -0
  235. package/tests/fixtures/react-project/src/App.tsx +77 -0
  236. package/tests/fixtures/svelte-project/package.json +11 -0
  237. package/tests/fixtures/svelte-project/src/App.svelte +369 -0
  238. package/tests/fixtures/vanilla-project/index.html +76 -0
  239. package/tests/fixtures/vanilla-project/script.js +331 -0
  240. package/tests/fixtures/vanilla-project/styles.css +359 -0
  241. package/tests/fixtures/vue-project/package.json +12 -0
  242. package/tests/fixtures/vue-project/src/App.vue +216 -0
  243. package/tsconfig.json +36 -0
  244. package/vitest.config.ts +10 -0
@@ -0,0 +1,459 @@
1
+ import type { Violation, Analysis, Fix, JulesSession, JulesActivity } from '../types/index.js';
2
+ import { GitHubManager } from '../git/github-manager.js';
3
+ import { FixManager } from './fix-manager.js';
4
+ import { ErrorHandler, APIError, ErrorType } from '../core/error-handler.js';
5
+ import chalk from 'chalk';
6
+
7
+ /**
8
+ * Jules AI implementer for autonomous code fixing
9
+ */
10
+ export class JulesImplementer {
11
+ private apiKey: string;
12
+ private baseUrl = 'https://jules.googleapis.com/v1alpha';
13
+ private githubManager: GitHubManager;
14
+ private fixManager: FixManager;
15
+
16
+ constructor(apiKey: string) {
17
+ this.apiKey = apiKey;
18
+ this.githubManager = new GitHubManager();
19
+ this.fixManager = new FixManager();
20
+ }
21
+
22
+ /**
23
+ * Generate a fix using Jules AI
24
+ */
25
+ async generateFix(violation: Violation, analysis: Analysis, repoSource?: string): Promise<Fix> {
26
+ const context = ErrorHandler.createContext('jules_fix_generation', {
27
+ feature: violation.feature,
28
+ file: violation.file,
29
+ browser: violation.browser
30
+ });
31
+
32
+ try {
33
+ // Get repository source if not provided
34
+ const source = repoSource || await this.githubManager.getCurrentSourceIdentifier();
35
+
36
+ // Create a session for this specific fix with retry logic
37
+ const session = await ErrorHandler.withRetry(
38
+ () => this.createSession(violation, analysis, source),
39
+ {
40
+ maxRetries: 2,
41
+ retryableErrors: [ErrorType.NETWORK, ErrorType.TIMEOUT, ErrorType.RATE_LIMIT, ErrorType.SERVER_ERROR]
42
+ }
43
+ );
44
+
45
+ // Monitor session activities until completion
46
+ const activities = await this.waitForCompletion(session.id);
47
+
48
+ // Extract the generated code changes
49
+ const fix = await this.extractFix(session.id, activities, violation, analysis);
50
+
51
+ return fix;
52
+ } catch (error) {
53
+ const apiError = ErrorHandler.handleAPIError(error, context);
54
+
55
+ // Log error for debugging
56
+ console.error('Jules fix generation failed:', {
57
+ feature: violation.feature,
58
+ error: apiError.message,
59
+ type: apiError.type
60
+ });
61
+
62
+ // Re-throw with proper error handling
63
+ throw apiError;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Create a Jules session for fixing
69
+ */
70
+ private async createSession(violation: Violation, analysis: Analysis, source: string): Promise<JulesSession> {
71
+ const prompt = this.buildFixPrompt(violation, analysis);
72
+
73
+ const response = await fetch(`${this.baseUrl}/sessions`, {
74
+ method: 'POST',
75
+ headers: {
76
+ 'Content-Type': 'application/json',
77
+ 'X-Goog-Api-Key': this.apiKey
78
+ },
79
+ body: JSON.stringify({
80
+ prompt: prompt,
81
+ sourceContext: {
82
+ source: source, // e.g., "sources/github/user/repo"
83
+ githubRepoContext: {
84
+ startingBranch: "main"
85
+ }
86
+ },
87
+ title: `Fix ${violation.feature} compatibility in ${violation.file}`,
88
+ requirePlanApproval: false // Auto-approve for BaseGuard automation
89
+ })
90
+ });
91
+
92
+ if (!response.ok) {
93
+ const errorText = await response.text();
94
+ const error = new Error(`Jules API error: ${response.status} ${response.statusText} - ${errorText}`);
95
+ (error as any).response = response;
96
+ throw error;
97
+ }
98
+
99
+ const sessionData = await response.json();
100
+
101
+ // Validate session response
102
+ ErrorHandler.validateAPIResponse(sessionData, ['id']);
103
+
104
+ return sessionData;
105
+ }
106
+
107
+ /**
108
+ * Wait for Jules session completion
109
+ */
110
+ private async waitForCompletion(sessionId: string): Promise<JulesActivity[]> {
111
+ let attempts = 0;
112
+ const maxAttempts = 30; // 5 minutes max (10 seconds * 30)
113
+
114
+ while (attempts < maxAttempts) {
115
+ const activities = await this.getActivities(sessionId);
116
+ const lastActivity = activities[activities.length - 1];
117
+
118
+ // Check if session is complete
119
+ if (lastActivity?.status === 'completed' || lastActivity?.type === 'agent_finished') {
120
+ return activities;
121
+ }
122
+
123
+ // Check for failure states
124
+ if (lastActivity?.status === 'failed' || lastActivity?.status === 'error') {
125
+ throw new Error(`Jules session failed: ${lastActivity.status}`);
126
+ }
127
+
128
+ // Wait 10 seconds before checking again
129
+ await new Promise(resolve => setTimeout(resolve, 10000));
130
+ attempts++;
131
+ }
132
+
133
+ throw new Error('Jules session timed out after 5 minutes');
134
+ }
135
+
136
+ /**
137
+ * Get activities for a Jules session
138
+ */
139
+ private async getActivities(sessionId: string): Promise<JulesActivity[]> {
140
+ const response = await fetch(`${this.baseUrl}/sessions/${sessionId}/activities`, {
141
+ headers: {
142
+ 'X-Goog-Api-Key': this.apiKey
143
+ }
144
+ });
145
+
146
+ if (!response.ok) {
147
+ const error = new Error(`Failed to get activities: ${response.status} ${response.statusText}`);
148
+ (error as any).response = response;
149
+ throw error;
150
+ }
151
+
152
+ const data = await response.json();
153
+
154
+ // Validate response structure
155
+ if (!data || typeof data !== 'object') {
156
+ throw new APIError(
157
+ 'Invalid activities response from Jules API',
158
+ ErrorType.VALIDATION,
159
+ {
160
+ suggestions: [
161
+ 'Check Jules API service status',
162
+ 'Verify session ID is valid',
163
+ 'Try the request again'
164
+ ]
165
+ }
166
+ );
167
+ }
168
+
169
+ return data.activities || [];
170
+ }
171
+
172
+ /**
173
+ * Extract fix from completed Jules session
174
+ */
175
+ private async extractFix(sessionId: string, activities: JulesActivity[], violation: Violation, analysis: Analysis): Promise<Fix> {
176
+ // Get the final session state to extract code changes
177
+ const sessionResponse = await fetch(`${this.baseUrl}/sessions/${sessionId}`, {
178
+ headers: {
179
+ 'X-Goog-Api-Key': this.apiKey
180
+ }
181
+ });
182
+
183
+ if (!sessionResponse.ok) {
184
+ throw new Error(`Failed to get session details: ${sessionResponse.status}`);
185
+ }
186
+
187
+ const sessionData = await sessionResponse.json();
188
+
189
+ // Extract code changes from activities or session data
190
+ const codeChanges = this.extractCodeChanges(activities, sessionData);
191
+
192
+ // Generate unified diff patch
193
+ const patch = this.generateUnifiedDiff(violation.file, codeChanges);
194
+
195
+ return {
196
+ violation,
197
+ analysis,
198
+ patch,
199
+ explanation: this.generateFixExplanation(violation, analysis, codeChanges),
200
+ filePath: violation.file,
201
+ preview: this.generatePreview(codeChanges),
202
+ confidence: 0.8, // Jules confidence score
203
+ testable: true
204
+ };
205
+ }
206
+
207
+ /**
208
+ * Extract code changes from Jules activities and session data
209
+ */
210
+ private extractCodeChanges(activities: JulesActivity[], sessionData: any): { original: string; modified: string } {
211
+ // Look for code changes in activities
212
+ const codeActivity = activities.find(activity =>
213
+ activity.type === 'code_change' || activity.type === 'file_edit'
214
+ );
215
+
216
+ if (codeActivity) {
217
+ // Extract from activity data (implementation depends on Jules API response format)
218
+ return {
219
+ original: sessionData.originalCode || '',
220
+ modified: sessionData.modifiedCode || ''
221
+ };
222
+ }
223
+
224
+ // Fallback: extract from session data
225
+ return {
226
+ original: sessionData.originalCode || '',
227
+ modified: sessionData.modifiedCode || ''
228
+ };
229
+ }
230
+
231
+ /**
232
+ * Generate unified diff patch
233
+ */
234
+ private generateUnifiedDiff(filePath: string, changes: { original: string; modified: string }): string {
235
+ const originalLines = changes.original.split('\n');
236
+ const modifiedLines = changes.modified.split('\n');
237
+
238
+ // Simple diff generation (in production, use a proper diff library)
239
+ let patch = `--- a/${filePath}\n+++ b/${filePath}\n`;
240
+
241
+ // Find differences and generate patch format
242
+ for (let i = 0; i < Math.max(originalLines.length, modifiedLines.length); i++) {
243
+ const originalLine = originalLines[i] || '';
244
+ const modifiedLine = modifiedLines[i] || '';
245
+
246
+ if (originalLine !== modifiedLine) {
247
+ if (originalLine) {
248
+ patch += `-${originalLine}\n`;
249
+ }
250
+ if (modifiedLine) {
251
+ patch += `+${modifiedLine}\n`;
252
+ }
253
+ }
254
+ }
255
+
256
+ return patch;
257
+ }
258
+
259
+ /**
260
+ * Generate fix explanation
261
+ */
262
+ private generateFixExplanation(violation: Violation, analysis: Analysis, changes: { original: string; modified: string }): string {
263
+ return `Fixed ${violation.feature} compatibility issue in ${violation.file}:\n\n` +
264
+ `- Added progressive enhancement using ${analysis.fixStrategy}\n` +
265
+ `- Implemented fallback for ${violation.browser} ${violation.required}\n` +
266
+ `- Applied best practices: ${analysis.bestPractices.join(', ')}\n\n` +
267
+ `This fix ensures the feature works across all target browsers while maintaining the original functionality.`;
268
+ }
269
+
270
+ /**
271
+ * Generate human-readable preview
272
+ */
273
+ private generatePreview(changes: { original: string; modified: string }): string {
274
+ const originalLines = changes.original.split('\n');
275
+ const modifiedLines = changes.modified.split('\n');
276
+
277
+ let preview = 'Changes:\n';
278
+
279
+ for (let i = 0; i < Math.max(originalLines.length, modifiedLines.length); i++) {
280
+ const originalLine = originalLines[i];
281
+ const modifiedLine = modifiedLines[i];
282
+
283
+ if (originalLine !== modifiedLine) {
284
+ if (originalLine) {
285
+ preview += `- ${originalLine}\n`;
286
+ }
287
+ if (modifiedLine) {
288
+ preview += `+ ${modifiedLine}\n`;
289
+ }
290
+ }
291
+ }
292
+
293
+ return preview;
294
+ }
295
+
296
+ /**
297
+ * Build fix prompt for Jules
298
+ */
299
+ private buildFixPrompt(violation: Violation, analysis: Analysis): string {
300
+ return `Fix browser compatibility issue in ${violation.file}:
301
+
302
+ ISSUE:
303
+ - Feature: ${violation.feature} (line ${violation.line})
304
+ - Unsupported in: ${violation.browser} ${violation.required}
305
+ - Baseline Status: ${violation.baselineStatus}
306
+ - Current code: ${violation.context}
307
+
308
+ ANALYSIS:
309
+ ${analysis.plainEnglish}
310
+
311
+ FIX STRATEGY:
312
+ ${analysis.fixStrategy}
313
+
314
+ REQUIREMENTS:
315
+ 1. Implement progressive enhancement using @supports for CSS features
316
+ 2. Use feature detection for JavaScript APIs
317
+ 3. Add appropriate fallbacks for older browsers
318
+ 4. Preserve all original functionality
319
+ 5. Follow best practices: ${analysis.bestPractices.join(', ')}
320
+ 6. Ensure the fix works in ${violation.browser} ${violation.required} and newer versions
321
+
322
+ Please fix this compatibility issue while maintaining the existing functionality. The fix should be production-ready and follow web standards.`;
323
+ }
324
+
325
+ /**
326
+ * Test Jules API connectivity
327
+ */
328
+ async testConnection(): Promise<{ success: boolean; error?: string; errorType?: ErrorType }> {
329
+ try {
330
+ const response = await fetch(`${this.baseUrl}/sessions`, {
331
+ method: 'GET',
332
+ headers: {
333
+ 'X-Goog-Api-Key': this.apiKey
334
+ }
335
+ });
336
+
337
+ if (response.ok || response.status === 404) {
338
+ // 404 is acceptable for sessions endpoint when no sessions exist
339
+ return { success: true };
340
+ } else {
341
+ const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
342
+ (error as any).response = response;
343
+ throw error;
344
+ }
345
+ } catch (error) {
346
+ const apiError = ErrorHandler.handleAPIError(error);
347
+
348
+ return {
349
+ success: false,
350
+ error: apiError.message,
351
+ errorType: apiError.type
352
+ };
353
+ }
354
+ }
355
+
356
+ /**
357
+ * Setup Jules GitHub integration
358
+ */
359
+ async setupGitHubIntegration(): Promise<string> {
360
+ return await this.githubManager.setupJulesGitHubIntegration();
361
+ }
362
+
363
+ /**
364
+ * Check if GitHub integration is set up
365
+ */
366
+ async isGitHubIntegrationSetup(): Promise<boolean> {
367
+ return await this.githubManager.isJulesIntegrationSetup();
368
+ }
369
+
370
+ /**
371
+ * Verify GitHub connection and permissions
372
+ */
373
+ async verifyGitHubConnection(): Promise<boolean> {
374
+ return await this.githubManager.verifyGitHubConnection();
375
+ }
376
+
377
+ /**
378
+ * Get repository information
379
+ */
380
+ getRepositoryInfo(): { owner: string | null; name: string | null } {
381
+ return this.githubManager.getRepositoryInfo();
382
+ }
383
+
384
+ /**
385
+ * Get current source identifier
386
+ */
387
+ async getSourceIdentifier(): Promise<string> {
388
+ return await this.githubManager.getCurrentSourceIdentifier();
389
+ }
390
+
391
+ /**
392
+ * Generate and apply fixes with interactive preview
393
+ */
394
+ async generateAndApplyFixes(violations: Violation[], analyses: Analysis[]): Promise<{ applied: Fix[]; skipped: Fix[]; failed: { fix: Fix; error: string }[] }> {
395
+ const fixes: Fix[] = [];
396
+
397
+ // Generate fixes for each violation
398
+ for (let i = 0; i < violations.length; i++) {
399
+ const violation = violations[i];
400
+ const analysis = analyses[i];
401
+
402
+ if (!violation || !analysis) {
403
+ console.log(chalk.red(`❌ Missing violation or analysis data for index ${i}`));
404
+ continue;
405
+ }
406
+
407
+ try {
408
+ console.log(chalk.cyan(`\n🔧 Generating fix ${i + 1}/${violations.length} for ${violation.feature}...`));
409
+ const fix = await this.generateFix(violation, analysis);
410
+ fixes.push(fix);
411
+ } catch (error) {
412
+ console.log(chalk.red(`❌ Failed to generate fix for ${violation.feature}: ${error instanceof Error ? error.message : 'Unknown error'}`));
413
+ }
414
+ }
415
+
416
+ if (fixes.length === 0) {
417
+ console.log(chalk.yellow('⚠️ No fixes were generated'));
418
+ return { applied: [], skipped: [], failed: [] };
419
+ }
420
+
421
+ // Apply fixes with interactive preview
422
+ return await this.fixManager.applyFixes(fixes);
423
+ }
424
+
425
+ /**
426
+ * Preview a single fix
427
+ */
428
+ async previewFix(fix: Fix): Promise<string> {
429
+ return await this.fixManager.generatePreview(fix);
430
+ }
431
+
432
+ /**
433
+ * Apply a single fix
434
+ */
435
+ async applySingleFix(fix: Fix): Promise<void> {
436
+ await this.fixManager.applyFix(fix);
437
+ }
438
+
439
+ /**
440
+ * Rollback applied fixes
441
+ */
442
+ async rollbackFix(filePath: string): Promise<void> {
443
+ await this.fixManager.rollbackFix(filePath);
444
+ }
445
+
446
+ /**
447
+ * Rollback all applied fixes
448
+ */
449
+ async rollbackAllFixes(): Promise<void> {
450
+ await this.fixManager.rollbackAllFixes();
451
+ }
452
+
453
+ /**
454
+ * Get list of applied fixes
455
+ */
456
+ getAppliedFixes(): string[] {
457
+ return this.fixManager.getAppliedFixes();
458
+ }
459
+ }