baseguard 1.0.1 ā 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.baseguardrc.example.json +64 -0
- package/.eslintrc.json +1 -1
- package/CHANGELOG.md +196 -0
- package/DEPLOYMENT.md +625 -0
- package/DEPLOYMENT_CHECKLIST.md +239 -0
- package/DEPLOYMENT_SUMMARY_v1.0.2.md +202 -0
- package/QUICK_START.md +134 -0
- package/README.md +447 -52
- package/RELEASE_NOTES_v1.0.2.md +434 -0
- package/bin/base.js +81 -61
- package/dist/ai/agentkit-orchestrator.d.ts +116 -0
- package/dist/ai/agentkit-orchestrator.d.ts.map +1 -0
- package/dist/ai/agentkit-orchestrator.js +417 -0
- package/dist/ai/agentkit-orchestrator.js.map +1 -0
- package/dist/ai/gemini-code-fixer.d.ts +85 -0
- package/dist/ai/gemini-code-fixer.d.ts.map +1 -0
- package/dist/ai/gemini-code-fixer.js +452 -0
- package/dist/ai/gemini-code-fixer.js.map +1 -0
- package/dist/ai/jules-implementer.d.ts +5 -4
- package/dist/ai/jules-implementer.d.ts.map +1 -1
- package/dist/ai/jules-implementer.js +6 -5
- package/dist/ai/jules-implementer.js.map +1 -1
- package/dist/ai/unified-code-fixer.d.ts +69 -0
- package/dist/ai/unified-code-fixer.d.ts.map +1 -0
- package/dist/ai/unified-code-fixer.js +289 -0
- package/dist/ai/unified-code-fixer.js.map +1 -0
- package/dist/commands/check.d.ts +3 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +166 -34
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +183 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +89 -91
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +16 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/status.d.ts +14 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +254 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/core/baseguard.d.ts +47 -5
- package/dist/core/baseguard.d.ts.map +1 -1
- package/dist/core/baseguard.js +506 -52
- package/dist/core/baseguard.js.map +1 -1
- package/dist/core/cache-manager.d.ts.map +1 -1
- package/dist/core/cache-manager.js +3 -1
- package/dist/core/cache-manager.js.map +1 -1
- package/dist/core/configuration-recovery.d.ts +116 -0
- package/dist/core/configuration-recovery.d.ts.map +1 -0
- package/dist/core/configuration-recovery.js +552 -0
- package/dist/core/configuration-recovery.js.map +1 -0
- package/dist/core/configuration.d.ts +4 -0
- package/dist/core/configuration.d.ts.map +1 -1
- package/dist/core/configuration.js +35 -0
- package/dist/core/configuration.js.map +1 -1
- package/dist/core/debug-logger.d.ts +181 -0
- package/dist/core/debug-logger.d.ts.map +1 -0
- package/dist/core/debug-logger.js +479 -0
- package/dist/core/debug-logger.js.map +1 -0
- package/dist/core/file-processor.d.ts.map +1 -1
- package/dist/core/file-processor.js +8 -2
- package/dist/core/file-processor.js.map +1 -1
- package/dist/core/graceful-degradation-manager.d.ts +123 -0
- package/dist/core/graceful-degradation-manager.d.ts.map +1 -0
- package/dist/core/graceful-degradation-manager.js +512 -0
- package/dist/core/graceful-degradation-manager.js.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/logger.d.ts +1 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +2 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/memory-manager.d.ts +84 -0
- package/dist/core/memory-manager.d.ts.map +1 -1
- package/dist/core/memory-manager.js +236 -1
- package/dist/core/memory-manager.js.map +1 -1
- package/dist/core/startup-optimizer.d.ts +14 -0
- package/dist/core/startup-optimizer.d.ts.map +1 -1
- package/dist/core/startup-optimizer.js +74 -3
- package/dist/core/startup-optimizer.js.map +1 -1
- package/dist/core/system-error-handler.d.ts +65 -0
- package/dist/core/system-error-handler.d.ts.map +1 -0
- package/dist/core/system-error-handler.js +653 -0
- package/dist/core/system-error-handler.js.map +1 -0
- package/dist/git/github-manager.d.ts +5 -16
- package/dist/git/github-manager.d.ts.map +1 -1
- package/dist/git/github-manager.js +6 -61
- package/dist/git/github-manager.js.map +1 -1
- package/dist/parsers/react-parser-optimized.d.ts +16 -0
- package/dist/parsers/react-parser-optimized.d.ts.map +1 -0
- package/dist/parsers/react-parser-optimized.js +147 -0
- package/dist/parsers/react-parser-optimized.js.map +1 -0
- package/dist/parsers/react-parser.d.ts.map +1 -1
- package/dist/parsers/react-parser.js +17 -15
- package/dist/parsers/react-parser.js.map +1 -1
- package/dist/parsers/svelte-parser.d.ts.map +1 -1
- package/dist/parsers/svelte-parser.js +7 -3
- package/dist/parsers/svelte-parser.js.map +1 -1
- package/dist/parsers/vanilla-parser.d.ts.map +1 -1
- package/dist/parsers/vanilla-parser.js +7 -3
- package/dist/parsers/vanilla-parser.js.map +1 -1
- package/dist/parsers/vue-parser.d.ts +18 -0
- package/dist/parsers/vue-parser.d.ts.map +1 -1
- package/dist/parsers/vue-parser.js +387 -1
- package/dist/parsers/vue-parser.js.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/ui/help.js +1 -1
- package/dist/ui/help.js.map +1 -1
- package/dist/ui/prompts.d.ts +7 -4
- package/dist/ui/prompts.d.ts.map +1 -1
- package/dist/ui/prompts.js +48 -55
- package/dist/ui/prompts.js.map +1 -1
- package/package.json +31 -6
- package/src/ai/__tests__/gemini-analyzer.test.ts +2 -2
- package/src/ai/agentkit-orchestrator.ts +534 -0
- package/src/ai/gemini-code-fixer.ts +540 -0
- package/src/ai/jules-implementer.ts +6 -5
- package/src/ai/unified-code-fixer.ts +347 -0
- package/src/commands/config.ts +126 -0
- package/src/commands/fix.ts +98 -94
- package/src/commands/init.ts +16 -2
- package/src/core/cache-manager.ts +4 -2
- package/src/core/configuration.ts +37 -0
- package/src/core/debug-logger.ts +2 -2
- package/src/core/file-processor.ts +10 -3
- package/src/core/index.ts +5 -1
- package/src/core/memory-manager.ts +4 -3
- package/src/core/startup-optimizer.ts +85 -3
- package/src/core/system-error-handler.ts +17 -11
- package/src/git/github-manager.ts +11 -79
- package/src/parsers/react-parser.ts +2 -2
- package/src/parsers/svelte-parser.ts +13 -9
- package/src/parsers/vanilla-parser.ts +18 -14
- package/src/parsers/vue-parser.ts +20 -14
- package/src/types/index.ts +4 -0
- package/src/ui/help.ts +1 -1
- package/src/ui/prompts.ts +54 -61
- package/test-build.js +41 -0
- package/tests/e2e/git-integration.e2e.test.ts +1 -1
- package/tsconfig.json +0 -1
- package/vitest.config.ts +4 -2
|
@@ -2,44 +2,21 @@ import { execSync } from 'child_process';
|
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* GitHub repository manager for Jules integration
|
|
9
|
+
* Note: GitHub app installation should be done on the Jules dashboard, not here
|
|
9
10
|
*/
|
|
10
11
|
export class GitHubManager {
|
|
11
12
|
private repoOwner: string | null = null;
|
|
12
13
|
private repoName: string | null = null;
|
|
13
14
|
private sourceIdentifier: string | null = null;
|
|
14
15
|
|
|
15
|
-
/**
|
|
16
|
-
* Guide user through Jules GitHub app installation
|
|
17
|
-
*/
|
|
18
|
-
async setupJulesGitHubIntegration(): Promise<string> {
|
|
19
|
-
console.log(chalk.cyan('\nš Setting up Jules GitHub Integration\n'));
|
|
20
|
-
|
|
21
|
-
// Step 1: Check if we're in a git repository
|
|
22
|
-
if (!this.isGitRepository()) {
|
|
23
|
-
throw new Error('Not in a git repository. Please run this command from within a git repository.');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Step 2: Get repository information
|
|
27
|
-
await this.detectRepositoryInfo();
|
|
28
|
-
|
|
29
|
-
// Step 3: Guide user through GitHub app installation
|
|
30
|
-
await this.guideGitHubAppInstallation();
|
|
31
|
-
|
|
32
|
-
// Step 4: Verify connection and get source identifier
|
|
33
|
-
const sourceId = await this.getSourceIdentifier();
|
|
34
|
-
|
|
35
|
-
console.log(chalk.green('ā
Jules GitHub integration setup complete!'));
|
|
36
|
-
return sourceId;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
16
|
/**
|
|
40
17
|
* Check if current directory is a git repository
|
|
41
18
|
*/
|
|
42
|
-
|
|
19
|
+
isGitRepository(): boolean {
|
|
43
20
|
try {
|
|
44
21
|
execSync('git rev-parse --git-dir', { stdio: 'ignore' });
|
|
45
22
|
return true;
|
|
@@ -51,7 +28,7 @@ export class GitHubManager {
|
|
|
51
28
|
/**
|
|
52
29
|
* Detect repository owner and name from git remote
|
|
53
30
|
*/
|
|
54
|
-
|
|
31
|
+
async detectRepositoryInfo(): Promise<void> {
|
|
55
32
|
try {
|
|
56
33
|
const remoteUrl = execSync('git config --get remote.origin.url', { encoding: 'utf8' }).trim();
|
|
57
34
|
|
|
@@ -71,59 +48,16 @@ export class GitHubManager {
|
|
|
71
48
|
}
|
|
72
49
|
}
|
|
73
50
|
|
|
74
|
-
/**
|
|
75
|
-
* Guide user through GitHub app installation process
|
|
76
|
-
*/
|
|
77
|
-
private async guideGitHubAppInstallation(): Promise<void> {
|
|
78
|
-
console.log(chalk.yellow('\nš Jules GitHub App Installation Steps:\n'));
|
|
79
|
-
|
|
80
|
-
console.log('1. Opening Jules GitHub app installation page...');
|
|
81
|
-
|
|
82
|
-
// Open Jules GitHub app installation URL
|
|
83
|
-
const installUrl = 'https://github.com/apps/jules-ai';
|
|
84
|
-
await open(installUrl);
|
|
85
|
-
|
|
86
|
-
console.log(chalk.dim(` ${installUrl}`));
|
|
87
|
-
|
|
88
|
-
console.log('\n2. Follow these steps in your browser:');
|
|
89
|
-
console.log(' ⢠Click "Install" on the Jules app page');
|
|
90
|
-
console.log(' ⢠Select your repository or organization');
|
|
91
|
-
console.log(` ⢠Grant access to ${this.repoOwner}/${this.repoName}`);
|
|
92
|
-
console.log(' ⢠Complete the installation process');
|
|
93
|
-
|
|
94
|
-
console.log('\n3. After installation:');
|
|
95
|
-
console.log(' ⢠Return to this terminal');
|
|
96
|
-
console.log(' ⢠The setup will continue automatically');
|
|
97
|
-
|
|
98
|
-
// Wait for user confirmation
|
|
99
|
-
await this.waitForUserConfirmation();
|
|
100
|
-
}
|
|
101
51
|
|
|
102
|
-
/**
|
|
103
|
-
* Wait for user to confirm GitHub app installation
|
|
104
|
-
*/
|
|
105
|
-
private async waitForUserConfirmation(): Promise<void> {
|
|
106
|
-
const { default: inquirer } = await import('inquirer');
|
|
107
|
-
|
|
108
|
-
const { confirmed } = await inquirer.prompt([
|
|
109
|
-
{
|
|
110
|
-
type: 'confirm',
|
|
111
|
-
name: 'confirmed',
|
|
112
|
-
message: 'Have you completed the Jules GitHub app installation?',
|
|
113
|
-
default: false
|
|
114
|
-
}
|
|
115
|
-
]);
|
|
116
|
-
|
|
117
|
-
if (!confirmed) {
|
|
118
|
-
console.log(chalk.yellow('\nPlease complete the GitHub app installation and run this command again.'));
|
|
119
|
-
process.exit(0);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
52
|
|
|
123
53
|
/**
|
|
124
54
|
* Get source identifier for Jules API
|
|
125
55
|
*/
|
|
126
|
-
|
|
56
|
+
async getSourceIdentifier(): Promise<string> {
|
|
57
|
+
if (!this.repoOwner || !this.repoName) {
|
|
58
|
+
await this.detectRepositoryInfo();
|
|
59
|
+
}
|
|
60
|
+
|
|
127
61
|
if (!this.repoOwner || !this.repoName) {
|
|
128
62
|
throw new Error('Repository information not available');
|
|
129
63
|
}
|
|
@@ -131,8 +65,6 @@ export class GitHubManager {
|
|
|
131
65
|
// Generate source identifier in the format expected by Jules
|
|
132
66
|
this.sourceIdentifier = `sources/github/${this.repoOwner}/${this.repoName}`;
|
|
133
67
|
|
|
134
|
-
console.log(chalk.blue(`š Source identifier: ${this.sourceIdentifier}`));
|
|
135
|
-
|
|
136
68
|
return this.sourceIdentifier;
|
|
137
69
|
}
|
|
138
70
|
|
|
@@ -174,7 +106,7 @@ export class GitHubManager {
|
|
|
174
106
|
}
|
|
175
107
|
|
|
176
108
|
/**
|
|
177
|
-
* Check if
|
|
109
|
+
* Check if we can detect repository information (GitHub integration is handled on Jules dashboard)
|
|
178
110
|
*/
|
|
179
111
|
async isJulesIntegrationSetup(): Promise<boolean> {
|
|
180
112
|
try {
|
|
@@ -183,7 +115,7 @@ export class GitHubManager {
|
|
|
183
115
|
}
|
|
184
116
|
|
|
185
117
|
await this.detectRepositoryInfo();
|
|
186
|
-
return
|
|
118
|
+
return this.repoOwner !== null && this.repoName !== null;
|
|
187
119
|
} catch {
|
|
188
120
|
return false;
|
|
189
121
|
}
|
|
@@ -278,7 +278,7 @@ export class ReactParser extends Parser {
|
|
|
278
278
|
const features: DetectedFeature[] = [];
|
|
279
279
|
|
|
280
280
|
// Check if this is likely a style object (has CSS-like properties)
|
|
281
|
-
const hasStyleProps = node.properties.some(prop => {
|
|
281
|
+
const hasStyleProps = node.properties.some((prop: any) => {
|
|
282
282
|
if (t.isObjectProperty(prop) && (t.isIdentifier(prop.key) || t.isStringLiteral(prop.key))) {
|
|
283
283
|
const key = t.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
|
|
284
284
|
return this.CSS_PROPERTIES.has(key) || key.includes('-') || key.startsWith('--');
|
|
@@ -290,7 +290,7 @@ export class ReactParser extends Parser {
|
|
|
290
290
|
return features;
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
node.properties.forEach(prop => {
|
|
293
|
+
node.properties.forEach((prop: any) => {
|
|
294
294
|
if (t.isObjectProperty(prop)) {
|
|
295
295
|
let key = '';
|
|
296
296
|
if (t.isIdentifier(prop.key)) {
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Parser } from './parser.js';
|
|
2
2
|
import type { DetectedFeature } from '../types/index.js';
|
|
3
3
|
import { LazyLoader } from '../core/lazy-loader.js';
|
|
4
|
+
import { parse as parseBabel } from '@babel/parser';
|
|
5
|
+
import traverse from '@babel/traverse';
|
|
6
|
+
import * as t from '@babel/types';
|
|
7
|
+
import postcss from 'postcss';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Parser for Svelte files (.svelte) - extracts ALL web platform features
|
|
@@ -177,7 +181,7 @@ export class SvelteParser extends Parser {
|
|
|
177
181
|
|
|
178
182
|
traverse(ast, {
|
|
179
183
|
// Extract JavaScript Web APIs
|
|
180
|
-
MemberExpression: (path) => {
|
|
184
|
+
MemberExpression: (path: any) => {
|
|
181
185
|
const feature = this.extractWebAPIFeature(path.node, scriptContent, scriptNode.start);
|
|
182
186
|
if (feature) {
|
|
183
187
|
features.push({ ...feature, file: filePath });
|
|
@@ -185,7 +189,7 @@ export class SvelteParser extends Parser {
|
|
|
185
189
|
},
|
|
186
190
|
|
|
187
191
|
// Extract function calls to Web APIs
|
|
188
|
-
CallExpression: (path) => {
|
|
192
|
+
CallExpression: (path: any) => {
|
|
189
193
|
const feature = this.extractWebAPICall(path.node, scriptContent, scriptNode.start);
|
|
190
194
|
if (feature) {
|
|
191
195
|
features.push({ ...feature, file: filePath });
|
|
@@ -193,7 +197,7 @@ export class SvelteParser extends Parser {
|
|
|
193
197
|
},
|
|
194
198
|
|
|
195
199
|
// Extract modern JavaScript syntax features
|
|
196
|
-
OptionalMemberExpression: (path) => {
|
|
200
|
+
OptionalMemberExpression: (path: any) => {
|
|
197
201
|
features.push({
|
|
198
202
|
feature: 'optional-chaining',
|
|
199
203
|
type: 'js',
|
|
@@ -205,7 +209,7 @@ export class SvelteParser extends Parser {
|
|
|
205
209
|
},
|
|
206
210
|
|
|
207
211
|
// Nullish coalescing
|
|
208
|
-
LogicalExpression: (path) => {
|
|
212
|
+
LogicalExpression: (path: any) => {
|
|
209
213
|
if (path.node.operator === '??') {
|
|
210
214
|
features.push({
|
|
211
215
|
feature: 'nullish-coalescing',
|
|
@@ -219,7 +223,7 @@ export class SvelteParser extends Parser {
|
|
|
219
223
|
},
|
|
220
224
|
|
|
221
225
|
// Private class fields
|
|
222
|
-
ClassPrivateProperty: (path) => {
|
|
226
|
+
ClassPrivateProperty: (path: any) => {
|
|
223
227
|
features.push({
|
|
224
228
|
feature: 'private-fields',
|
|
225
229
|
type: 'js',
|
|
@@ -231,7 +235,7 @@ export class SvelteParser extends Parser {
|
|
|
231
235
|
},
|
|
232
236
|
|
|
233
237
|
// Top-level await
|
|
234
|
-
AwaitExpression: (path) => {
|
|
238
|
+
AwaitExpression: (path: any) => {
|
|
235
239
|
if (this.isTopLevelAwait(path)) {
|
|
236
240
|
features.push({
|
|
237
241
|
feature: 'top-level-await',
|
|
@@ -265,7 +269,7 @@ export class SvelteParser extends Parser {
|
|
|
265
269
|
|
|
266
270
|
const root = postcss.parse(styleContent);
|
|
267
271
|
|
|
268
|
-
root.walkDecls(decl => {
|
|
272
|
+
root.walkDecls((decl: any) => {
|
|
269
273
|
features.push({
|
|
270
274
|
feature: decl.prop,
|
|
271
275
|
type: 'css',
|
|
@@ -276,7 +280,7 @@ export class SvelteParser extends Parser {
|
|
|
276
280
|
});
|
|
277
281
|
});
|
|
278
282
|
|
|
279
|
-
root.walkRules(rule => {
|
|
283
|
+
root.walkRules((rule: any) => {
|
|
280
284
|
// Extract CSS selectors that might be modern features
|
|
281
285
|
if (rule.selector.includes(':has(') ||
|
|
282
286
|
rule.selector.includes(':is(') ||
|
|
@@ -293,7 +297,7 @@ export class SvelteParser extends Parser {
|
|
|
293
297
|
}
|
|
294
298
|
});
|
|
295
299
|
|
|
296
|
-
root.walkAtRules(atRule => {
|
|
300
|
+
root.walkAtRules((atRule: any) => {
|
|
297
301
|
// Extract at-rules like @supports, @container, etc.
|
|
298
302
|
features.push({
|
|
299
303
|
feature: `@${atRule.name}`,
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Parser } from './parser.js';
|
|
2
2
|
import type { DetectedFeature } from '../types/index.js';
|
|
3
3
|
import { LazyLoader } from '../core/lazy-loader.js';
|
|
4
|
+
import { parse as parseBabel } from '@babel/parser';
|
|
5
|
+
import traverse from '@babel/traverse';
|
|
6
|
+
import * as t from '@babel/types';
|
|
7
|
+
import postcss from 'postcss';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Vanilla JavaScript/CSS/HTML parser - extracts ALL web platform features
|
|
@@ -280,7 +284,7 @@ export class VanillaParser extends Parser {
|
|
|
280
284
|
|
|
281
285
|
traverse(ast, {
|
|
282
286
|
// Extract Web API member expressions
|
|
283
|
-
MemberExpression: (path) => {
|
|
287
|
+
MemberExpression: (path: any) => {
|
|
284
288
|
const feature = this.extractWebAPIFeature(path.node, content);
|
|
285
289
|
if (feature) {
|
|
286
290
|
features.push({ ...feature, file: filePath });
|
|
@@ -288,7 +292,7 @@ export class VanillaParser extends Parser {
|
|
|
288
292
|
},
|
|
289
293
|
|
|
290
294
|
// Extract Web API function calls
|
|
291
|
-
CallExpression: (path) => {
|
|
295
|
+
CallExpression: (path: any) => {
|
|
292
296
|
const feature = this.extractWebAPICall(path.node, content);
|
|
293
297
|
if (feature) {
|
|
294
298
|
features.push({ ...feature, file: filePath });
|
|
@@ -296,7 +300,7 @@ export class VanillaParser extends Parser {
|
|
|
296
300
|
},
|
|
297
301
|
|
|
298
302
|
// Modern JavaScript syntax features
|
|
299
|
-
OptionalMemberExpression: (path) => {
|
|
303
|
+
OptionalMemberExpression: (path: any) => {
|
|
300
304
|
features.push({
|
|
301
305
|
feature: 'optional-chaining',
|
|
302
306
|
type: 'js',
|
|
@@ -307,7 +311,7 @@ export class VanillaParser extends Parser {
|
|
|
307
311
|
});
|
|
308
312
|
},
|
|
309
313
|
|
|
310
|
-
OptionalCallExpression: (path) => {
|
|
314
|
+
OptionalCallExpression: (path: any) => {
|
|
311
315
|
features.push({
|
|
312
316
|
feature: 'optional-chaining',
|
|
313
317
|
type: 'js',
|
|
@@ -319,7 +323,7 @@ export class VanillaParser extends Parser {
|
|
|
319
323
|
},
|
|
320
324
|
|
|
321
325
|
// Nullish coalescing
|
|
322
|
-
LogicalExpression: (path) => {
|
|
326
|
+
LogicalExpression: (path: any) => {
|
|
323
327
|
if (path.node.operator === '??') {
|
|
324
328
|
features.push({
|
|
325
329
|
feature: 'nullish-coalescing',
|
|
@@ -333,7 +337,7 @@ export class VanillaParser extends Parser {
|
|
|
333
337
|
},
|
|
334
338
|
|
|
335
339
|
// Private class fields
|
|
336
|
-
ClassPrivateProperty: (path) => {
|
|
340
|
+
ClassPrivateProperty: (path: any) => {
|
|
337
341
|
features.push({
|
|
338
342
|
feature: 'private-fields',
|
|
339
343
|
type: 'js',
|
|
@@ -344,7 +348,7 @@ export class VanillaParser extends Parser {
|
|
|
344
348
|
});
|
|
345
349
|
},
|
|
346
350
|
|
|
347
|
-
ClassPrivateMethod: (path) => {
|
|
351
|
+
ClassPrivateMethod: (path: any) => {
|
|
348
352
|
features.push({
|
|
349
353
|
feature: 'private-methods',
|
|
350
354
|
type: 'js',
|
|
@@ -356,7 +360,7 @@ export class VanillaParser extends Parser {
|
|
|
356
360
|
},
|
|
357
361
|
|
|
358
362
|
// Top-level await
|
|
359
|
-
AwaitExpression: (path) => {
|
|
363
|
+
AwaitExpression: (path: any) => {
|
|
360
364
|
if (this.isTopLevelAwait(path)) {
|
|
361
365
|
features.push({
|
|
362
366
|
feature: 'top-level-await',
|
|
@@ -370,7 +374,7 @@ export class VanillaParser extends Parser {
|
|
|
370
374
|
},
|
|
371
375
|
|
|
372
376
|
// Dynamic imports
|
|
373
|
-
Import: (path) => {
|
|
377
|
+
Import: (path: any) => {
|
|
374
378
|
features.push({
|
|
375
379
|
feature: 'dynamic-import',
|
|
376
380
|
type: 'js',
|
|
@@ -382,7 +386,7 @@ export class VanillaParser extends Parser {
|
|
|
382
386
|
},
|
|
383
387
|
|
|
384
388
|
// BigInt literals
|
|
385
|
-
BigIntLiteral: (path) => {
|
|
389
|
+
BigIntLiteral: (path: any) => {
|
|
386
390
|
features.push({
|
|
387
391
|
feature: 'bigint',
|
|
388
392
|
type: 'js',
|
|
@@ -394,7 +398,7 @@ export class VanillaParser extends Parser {
|
|
|
394
398
|
},
|
|
395
399
|
|
|
396
400
|
// Numeric separators
|
|
397
|
-
NumericLiteral: (path) => {
|
|
401
|
+
NumericLiteral: (path: any) => {
|
|
398
402
|
if ((path.node.extra as any)?.raw?.includes('_')) {
|
|
399
403
|
features.push({
|
|
400
404
|
feature: 'numeric-separators',
|
|
@@ -422,7 +426,7 @@ export class VanillaParser extends Parser {
|
|
|
422
426
|
const root = postcss.parse(content);
|
|
423
427
|
|
|
424
428
|
// Extract CSS properties
|
|
425
|
-
root.walkDecls(decl => {
|
|
429
|
+
root.walkDecls((decl: any) => {
|
|
426
430
|
if (this.CSS_PROPERTIES.has(decl.prop) || decl.prop.startsWith('--')) {
|
|
427
431
|
features.push({
|
|
428
432
|
feature: decl.prop,
|
|
@@ -453,7 +457,7 @@ export class VanillaParser extends Parser {
|
|
|
453
457
|
});
|
|
454
458
|
|
|
455
459
|
// Extract CSS selectors
|
|
456
|
-
root.walkRules(rule => {
|
|
460
|
+
root.walkRules((rule: any) => {
|
|
457
461
|
this.CSS_SELECTORS.forEach(selector => {
|
|
458
462
|
if (rule.selector.includes(selector)) {
|
|
459
463
|
features.push({
|
|
@@ -469,7 +473,7 @@ export class VanillaParser extends Parser {
|
|
|
469
473
|
});
|
|
470
474
|
|
|
471
475
|
// Extract at-rules
|
|
472
|
-
root.walkAtRules(atRule => {
|
|
476
|
+
root.walkAtRules((atRule: any) => {
|
|
473
477
|
const atRuleName = `@${atRule.name}`;
|
|
474
478
|
features.push({
|
|
475
479
|
feature: atRuleName,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Parser } from './parser.js';
|
|
2
2
|
import type { DetectedFeature } from '../types/index.js';
|
|
3
3
|
import { LazyLoader } from '../core/lazy-loader.js';
|
|
4
|
+
import traverse from '@babel/traverse';
|
|
5
|
+
import * as t from '@babel/types';
|
|
6
|
+
import postcss from 'postcss';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Vue single-file component parser - extracts ALL web platform features
|
|
@@ -165,7 +168,7 @@ export class VueParser extends Parser {
|
|
|
165
168
|
|
|
166
169
|
traverse(ast, {
|
|
167
170
|
// Extract JavaScript Web APIs
|
|
168
|
-
MemberExpression: (path) => {
|
|
171
|
+
MemberExpression: (path: any) => {
|
|
169
172
|
const feature = this.extractWebAPIFeature(path.node, path, content);
|
|
170
173
|
if (feature) {
|
|
171
174
|
features.push({ ...feature, file: filePath });
|
|
@@ -173,7 +176,7 @@ export class VueParser extends Parser {
|
|
|
173
176
|
},
|
|
174
177
|
|
|
175
178
|
// Extract function calls to Web APIs
|
|
176
|
-
CallExpression: (path) => {
|
|
179
|
+
CallExpression: (path: any) => {
|
|
177
180
|
const feature = this.extractWebAPICall(path.node, path, content);
|
|
178
181
|
if (feature) {
|
|
179
182
|
features.push({ ...feature, file: filePath });
|
|
@@ -181,7 +184,7 @@ export class VueParser extends Parser {
|
|
|
181
184
|
},
|
|
182
185
|
|
|
183
186
|
// Extract modern JavaScript syntax features
|
|
184
|
-
OptionalMemberExpression: (path) => {
|
|
187
|
+
OptionalMemberExpression: (path: any) => {
|
|
185
188
|
features.push({
|
|
186
189
|
feature: 'optional-chaining',
|
|
187
190
|
type: 'js',
|
|
@@ -193,7 +196,7 @@ export class VueParser extends Parser {
|
|
|
193
196
|
},
|
|
194
197
|
|
|
195
198
|
// Nullish coalescing
|
|
196
|
-
LogicalExpression: (path) => {
|
|
199
|
+
LogicalExpression: (path: any) => {
|
|
197
200
|
if (path.node.operator === '??') {
|
|
198
201
|
features.push({
|
|
199
202
|
feature: 'nullish-coalescing',
|
|
@@ -207,7 +210,7 @@ export class VueParser extends Parser {
|
|
|
207
210
|
},
|
|
208
211
|
|
|
209
212
|
// Private class fields
|
|
210
|
-
ClassPrivateProperty: (path) => {
|
|
213
|
+
ClassPrivateProperty: (path: any) => {
|
|
211
214
|
features.push({
|
|
212
215
|
feature: 'private-fields',
|
|
213
216
|
type: 'js',
|
|
@@ -219,7 +222,7 @@ export class VueParser extends Parser {
|
|
|
219
222
|
},
|
|
220
223
|
|
|
221
224
|
// Top-level await
|
|
222
|
-
AwaitExpression: (path) => {
|
|
225
|
+
AwaitExpression: (path: any) => {
|
|
223
226
|
if (this.isTopLevelAwait(path)) {
|
|
224
227
|
features.push({
|
|
225
228
|
feature: 'top-level-await',
|
|
@@ -250,7 +253,7 @@ export class VueParser extends Parser {
|
|
|
250
253
|
const postcss = await LazyLoader.getPostCSS();
|
|
251
254
|
const root = postcss.parse(content);
|
|
252
255
|
|
|
253
|
-
root.walkDecls(decl => {
|
|
256
|
+
root.walkDecls((decl: any) => {
|
|
254
257
|
features.push({
|
|
255
258
|
feature: decl.prop,
|
|
256
259
|
type: 'css',
|
|
@@ -261,7 +264,7 @@ export class VueParser extends Parser {
|
|
|
261
264
|
});
|
|
262
265
|
});
|
|
263
266
|
|
|
264
|
-
root.walkRules(rule => {
|
|
267
|
+
root.walkRules((rule: any) => {
|
|
265
268
|
// Extract CSS selectors that might be modern features
|
|
266
269
|
if (rule.selector.includes(':has(') ||
|
|
267
270
|
rule.selector.includes(':is(') ||
|
|
@@ -278,7 +281,7 @@ export class VueParser extends Parser {
|
|
|
278
281
|
}
|
|
279
282
|
});
|
|
280
283
|
|
|
281
|
-
root.walkAtRules(atRule => {
|
|
284
|
+
root.walkAtRules((atRule: any) => {
|
|
282
285
|
// Extract at-rules like @supports, @container, etc.
|
|
283
286
|
features.push({
|
|
284
287
|
feature: `@${atRule.name}`,
|
|
@@ -305,13 +308,13 @@ export class VueParser extends Parser {
|
|
|
305
308
|
const lines = content.split('\n');
|
|
306
309
|
|
|
307
310
|
lines.forEach((line, index) => {
|
|
308
|
-
let match;
|
|
311
|
+
let match: RegExpExecArray | null;
|
|
309
312
|
while ((match = htmlElementRegex.exec(line)) !== null) {
|
|
310
313
|
const tagName = match[1];
|
|
311
314
|
const attributes = match[2];
|
|
312
315
|
|
|
313
316
|
// Check for modern HTML elements
|
|
314
|
-
if (this.isModernHTMLElement(tagName)) {
|
|
317
|
+
if (tagName && this.isModernHTMLElement(tagName)) {
|
|
315
318
|
features.push({
|
|
316
319
|
feature: tagName,
|
|
317
320
|
type: 'html',
|
|
@@ -331,7 +334,7 @@ export class VueParser extends Parser {
|
|
|
331
334
|
type: 'html',
|
|
332
335
|
context: line.trim(),
|
|
333
336
|
line: index + 1,
|
|
334
|
-
column: match
|
|
337
|
+
column: match!.index,
|
|
335
338
|
file: filePath
|
|
336
339
|
});
|
|
337
340
|
});
|
|
@@ -447,8 +450,11 @@ export class VueParser extends Parser {
|
|
|
447
450
|
modernAttrPatterns.forEach(pattern => {
|
|
448
451
|
if (pattern.test(attributes)) {
|
|
449
452
|
const match = attributes.match(pattern);
|
|
450
|
-
if (match) {
|
|
451
|
-
|
|
453
|
+
if (match && match[0]) {
|
|
454
|
+
const attrName = match[0].split('=')[0];
|
|
455
|
+
if (attrName) {
|
|
456
|
+
modernAttrs.push(attrName);
|
|
457
|
+
}
|
|
452
458
|
}
|
|
453
459
|
}
|
|
454
460
|
});
|
package/src/types/index.ts
CHANGED
|
@@ -50,6 +50,10 @@ export interface Configuration {
|
|
|
50
50
|
jules: string | null;
|
|
51
51
|
gemini: string | null;
|
|
52
52
|
};
|
|
53
|
+
codingAgent: {
|
|
54
|
+
primary: 'jules' | 'gemini';
|
|
55
|
+
fallback: 'jules' | 'gemini';
|
|
56
|
+
};
|
|
53
57
|
automation: {
|
|
54
58
|
enabled: boolean;
|
|
55
59
|
trigger: 'pre-commit' | 'pre-push';
|
package/src/ui/help.ts
CHANGED
|
@@ -138,7 +138,7 @@ export function showGlobalHelp(): void {
|
|
|
138
138
|
console.log(chalk.white('AI SERVICES:'));
|
|
139
139
|
console.log(` ${chalk.cyan('Gemini:')} AI analysis of compatibility issues`);
|
|
140
140
|
console.log(` Get API key: ${chalk.blue('https://aistudio.google.com')}`);
|
|
141
|
-
console.log(` ${chalk.cyan('Jules:')} Autonomous code fixing
|
|
141
|
+
console.log(` ${chalk.cyan('Jules:')} Autonomous code fixing (requires GitHub repository)`);
|
|
142
142
|
console.log(` Get API key: ${chalk.blue('https://jules.google.com')}\n`);
|
|
143
143
|
|
|
144
144
|
console.log(chalk.white('SUPPORTED FILES:'));
|
package/src/ui/prompts.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
import open from 'open';
|
|
3
|
+
import chalk from 'chalk';
|
|
3
4
|
import { Colors, UIComponents } from './components.js';
|
|
4
5
|
import { ApiKeyManager } from '../core/api-key-manager.js';
|
|
5
6
|
import type { BrowserTarget } from '../types/index.js';
|
|
@@ -300,8 +301,8 @@ export class Prompts {
|
|
|
300
301
|
if (testResult.success) {
|
|
301
302
|
spinner.succeed('Jules API key validated successfully');
|
|
302
303
|
|
|
303
|
-
//
|
|
304
|
-
|
|
304
|
+
// Note: GitHub integration should be set up on the Jules dashboard
|
|
305
|
+
console.log(chalk.cyan('š” Note: GitHub integration should be configured on the Jules dashboard.'));
|
|
305
306
|
|
|
306
307
|
return keyPrompt.apiKey;
|
|
307
308
|
} else {
|
|
@@ -329,66 +330,7 @@ export class Prompts {
|
|
|
329
330
|
return undefined;
|
|
330
331
|
}
|
|
331
332
|
|
|
332
|
-
/**
|
|
333
|
-
* Guide user through Jules GitHub app installation
|
|
334
|
-
*/
|
|
335
|
-
static async setupJulesGitHubIntegration(): Promise<void> {
|
|
336
|
-
console.log(Colors.info('\nš Setting up Jules GitHub integration'));
|
|
337
|
-
|
|
338
|
-
const setupGitHub = await inquirer.prompt([
|
|
339
|
-
{
|
|
340
|
-
type: 'confirm',
|
|
341
|
-
name: 'setup',
|
|
342
|
-
message: 'Jules needs access to your GitHub repository for code fixing. Set up now?',
|
|
343
|
-
default: true
|
|
344
|
-
}
|
|
345
|
-
]);
|
|
346
|
-
|
|
347
|
-
if (!setupGitHub.setup) {
|
|
348
|
-
UIComponents.showWarningBox('GitHub integration skipped. Jules will have limited functionality without repository access.');
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const openGitHub = await inquirer.prompt([
|
|
353
|
-
{
|
|
354
|
-
type: 'confirm',
|
|
355
|
-
name: 'open',
|
|
356
|
-
message: 'Open GitHub to install the Jules app?',
|
|
357
|
-
default: true
|
|
358
|
-
}
|
|
359
|
-
]);
|
|
360
|
-
|
|
361
|
-
if (openGitHub.open) {
|
|
362
|
-
const spinner = UIComponents.createSpinner('Opening GitHub Apps...');
|
|
363
|
-
spinner.start();
|
|
364
|
-
|
|
365
|
-
try {
|
|
366
|
-
await open('https://github.com/apps/jules-ai');
|
|
367
|
-
spinner.succeed('Opened Jules GitHub App page');
|
|
368
|
-
} catch (error) {
|
|
369
|
-
spinner.fail('Failed to open browser. Please visit https://github.com/apps/jules-ai manually');
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
333
|
|
|
373
|
-
console.log(Colors.muted('\nSteps to install Jules GitHub app:'));
|
|
374
|
-
UIComponents.showList([
|
|
375
|
-
'Click "Install" on the Jules GitHub app page',
|
|
376
|
-
'Select the repositories you want Jules to access',
|
|
377
|
-
'Complete the installation process',
|
|
378
|
-
'Return here when done'
|
|
379
|
-
]);
|
|
380
|
-
|
|
381
|
-
await inquirer.prompt([
|
|
382
|
-
{
|
|
383
|
-
type: 'confirm',
|
|
384
|
-
name: 'completed',
|
|
385
|
-
message: 'Have you completed the GitHub app installation?',
|
|
386
|
-
default: false
|
|
387
|
-
}
|
|
388
|
-
]);
|
|
389
|
-
|
|
390
|
-
UIComponents.showSuccessBox('Jules GitHub integration setup complete!');
|
|
391
|
-
}
|
|
392
334
|
|
|
393
335
|
/**
|
|
394
336
|
* Set up Gemini API key with browser integration
|
|
@@ -685,4 +627,55 @@ export class Prompts {
|
|
|
685
627
|
}
|
|
686
628
|
]);
|
|
687
629
|
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Choose coding agent for fixing
|
|
633
|
+
*/
|
|
634
|
+
static async chooseCodingAgent(): Promise<{ primary: 'jules' | 'gemini'; fallback: 'jules' | 'gemini' }> {
|
|
635
|
+
console.log(chalk.cyan('\nš¤ Coding Agent Selection'));
|
|
636
|
+
console.log(chalk.dim('Choose which AI agent to use for code fixing:\n'));
|
|
637
|
+
|
|
638
|
+
console.log(chalk.white('Jules (Google\'s Autonomous Coding Agent):'));
|
|
639
|
+
console.log(chalk.green(' ā
Autonomous operation in cloud VMs'));
|
|
640
|
+
console.log(chalk.green(' ā
Full repository context understanding'));
|
|
641
|
+
console.log(chalk.green(' ā
Asynchronous processing'));
|
|
642
|
+
console.log(chalk.red(' ā Requires GitHub repository'));
|
|
643
|
+
console.log(chalk.red(' ā Cannot work with local/uncommitted files'));
|
|
644
|
+
|
|
645
|
+
console.log(chalk.white('\nGemini 2.5 Pro (Direct API Integration):'));
|
|
646
|
+
console.log(chalk.green(' ā
Works with any files (GitHub or not)'));
|
|
647
|
+
console.log(chalk.green(' ā
Immediate processing'));
|
|
648
|
+
console.log(chalk.green(' ā
Works with uncommitted/local files'));
|
|
649
|
+
console.log(chalk.green(' ā
Grounded with real-time web search'));
|
|
650
|
+
console.log(chalk.yellow(' ā ļø Requires manual code application'));
|
|
651
|
+
|
|
652
|
+
const answers = await inquirer.prompt([
|
|
653
|
+
{
|
|
654
|
+
type: 'list',
|
|
655
|
+
name: 'primary',
|
|
656
|
+
message: 'Select primary coding agent:',
|
|
657
|
+
choices: [
|
|
658
|
+
{ name: 'Gemini 2.5 Pro (recommended for most projects)', value: 'gemini' },
|
|
659
|
+
{ name: 'Jules (for GitHub repositories with autonomous needs)', value: 'jules' }
|
|
660
|
+
],
|
|
661
|
+
default: 'gemini'
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
type: 'list',
|
|
665
|
+
name: 'fallback',
|
|
666
|
+
message: 'Select fallback coding agent:',
|
|
667
|
+
choices: [
|
|
668
|
+
{ name: 'Gemini 2.5 Pro', value: 'gemini' },
|
|
669
|
+
{ name: 'Jules', value: 'jules' }
|
|
670
|
+
],
|
|
671
|
+
default: 'gemini'
|
|
672
|
+
}
|
|
673
|
+
]);
|
|
674
|
+
|
|
675
|
+
console.log(chalk.green(`\nā
Coding agents configured:`));
|
|
676
|
+
console.log(` Primary: ${answers.primary}`);
|
|
677
|
+
console.log(` Fallback: ${answers.fallback}`);
|
|
678
|
+
|
|
679
|
+
return answers;
|
|
680
|
+
}
|
|
688
681
|
}
|