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