baseguard 1.0.2 ā 1.0.4
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 +63 -63
- package/.eslintrc.json +24 -24
- package/.prettierrc +7 -7
- package/CHANGELOG.md +195 -195
- package/DEPLOYMENT.md +624 -624
- package/DEPLOYMENT_CHECKLIST.md +239 -239
- package/DEPLOYMENT_SUMMARY_v1.0.2.md +202 -202
- package/QUICK_START.md +134 -134
- package/README.md +488 -488
- package/RELEASE_NOTES_v1.0.2.md +434 -434
- package/bin/base.js +628 -613
- package/dist/ai/fix-manager.d.ts.map +1 -1
- package/dist/ai/fix-manager.js +1 -1
- package/dist/ai/fix-manager.js.map +1 -1
- package/dist/ai/gemini-analyzer.d.ts.map +1 -1
- package/dist/ai/gemini-analyzer.js +29 -35
- package/dist/ai/gemini-analyzer.js.map +1 -1
- package/dist/ai/gemini-code-fixer.d.ts.map +1 -1
- package/dist/ai/gemini-code-fixer.js +58 -58
- package/dist/ai/gemini-code-fixer.js.map +1 -1
- package/dist/ai/jules-implementer.d.ts +3 -0
- package/dist/ai/jules-implementer.d.ts.map +1 -1
- package/dist/ai/jules-implementer.js +63 -32
- package/dist/ai/jules-implementer.js.map +1 -1
- package/dist/ai/unified-code-fixer.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +1 -1
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/config.js +2 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +44 -15
- package/dist/commands/fix.js.map +1 -1
- package/dist/core/api-key-manager.js +2 -2
- package/dist/core/api-key-manager.js.map +1 -1
- package/dist/core/baseguard.d.ts +1 -0
- package/dist/core/baseguard.d.ts.map +1 -1
- package/dist/core/baseguard.js +13 -10
- package/dist/core/baseguard.js.map +1 -1
- package/dist/core/baseline-checker.d.ts.map +1 -1
- package/dist/core/baseline-checker.js +2 -1
- package/dist/core/baseline-checker.js.map +1 -1
- package/dist/core/configuration-recovery.d.ts.map +1 -1
- package/dist/core/configuration-recovery.js +1 -1
- package/dist/core/configuration-recovery.js.map +1 -1
- package/dist/core/debug-logger.d.ts.map +1 -1
- package/dist/core/debug-logger.js +1 -1
- package/dist/core/debug-logger.js.map +1 -1
- package/dist/core/error-handler.d.ts.map +1 -1
- package/dist/core/error-handler.js +2 -1
- package/dist/core/error-handler.js.map +1 -1
- package/dist/core/gitignore-manager.js +5 -5
- package/dist/core/graceful-degradation-manager.d.ts.map +1 -1
- package/dist/core/graceful-degradation-manager.js +16 -16
- package/dist/core/graceful-degradation-manager.js.map +1 -1
- package/dist/core/lazy-loader.d.ts.map +1 -1
- package/dist/core/lazy-loader.js +9 -2
- package/dist/core/lazy-loader.js.map +1 -1
- package/dist/core/memory-manager.d.ts +0 -3
- package/dist/core/memory-manager.d.ts.map +1 -1
- package/dist/core/memory-manager.js.map +1 -1
- package/dist/core/parser-worker.d.ts +2 -0
- package/dist/core/parser-worker.d.ts.map +1 -0
- package/dist/core/parser-worker.js +19 -0
- package/dist/core/parser-worker.js.map +1 -0
- package/dist/core/startup-optimizer.d.ts +2 -0
- package/dist/core/startup-optimizer.d.ts.map +1 -1
- package/dist/core/startup-optimizer.js +19 -12
- package/dist/core/startup-optimizer.js.map +1 -1
- package/dist/core/system-error-handler.d.ts.map +1 -1
- package/dist/core/system-error-handler.js +18 -11
- package/dist/core/system-error-handler.js.map +1 -1
- package/dist/git/automation-engine.d.ts.map +1 -1
- package/dist/git/automation-engine.js +5 -4
- package/dist/git/automation-engine.js.map +1 -1
- package/dist/git/github-manager.d.ts.map +1 -1
- package/dist/git/github-manager.js.map +1 -1
- package/dist/git/hook-manager.js +5 -5
- package/dist/git/hook-manager.js.map +1 -1
- package/dist/parsers/parser-manager.d.ts.map +1 -1
- package/dist/parsers/parser-manager.js +1 -1
- package/dist/parsers/parser-manager.js.map +1 -1
- package/dist/parsers/svelte-parser.js +1 -1
- 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.map +1 -1
- package/dist/parsers/vue-parser.d.ts.map +1 -1
- package/dist/parsers/vue-parser.js.map +1 -1
- package/dist/ui/components.d.ts +1 -1
- package/dist/ui/components.d.ts.map +1 -1
- package/dist/ui/components.js +11 -11
- package/dist/ui/components.js.map +1 -1
- package/dist/ui/terminal-header.js +14 -14
- package/package.json +105 -105
- package/src/ai/__tests__/gemini-analyzer.test.ts +180 -180
- package/src/ai/agentkit-orchestrator.ts +533 -533
- package/src/ai/fix-manager.ts +362 -362
- package/src/ai/gemini-analyzer.ts +665 -671
- package/src/ai/gemini-code-fixer.ts +539 -540
- package/src/ai/index.ts +3 -3
- package/src/ai/jules-implementer.ts +504 -460
- package/src/ai/unified-code-fixer.ts +347 -347
- package/src/commands/automation.ts +343 -343
- package/src/commands/check.ts +298 -299
- package/src/commands/config.ts +584 -583
- package/src/commands/fix.ts +264 -238
- package/src/commands/index.ts +6 -6
- package/src/commands/init.ts +155 -155
- package/src/commands/status.ts +306 -306
- package/src/core/api-key-manager.ts +298 -298
- package/src/core/baseguard.ts +757 -756
- package/src/core/baseline-checker.ts +564 -563
- package/src/core/cache-manager.ts +271 -271
- package/src/core/configuration-recovery.ts +672 -673
- package/src/core/configuration.ts +595 -595
- package/src/core/debug-logger.ts +590 -590
- package/src/core/directory-filter.ts +420 -420
- package/src/core/error-handler.ts +518 -517
- package/src/core/file-processor.ts +337 -337
- package/src/core/gitignore-manager.ts +168 -168
- package/src/core/graceful-degradation-manager.ts +596 -596
- package/src/core/index.ts +16 -16
- package/src/core/lazy-loader.ts +317 -307
- package/src/core/memory-manager.ts +290 -295
- package/src/core/parser-worker.ts +33 -0
- package/src/core/startup-optimizer.ts +246 -243
- package/src/core/system-error-handler.ts +755 -750
- package/src/git/automation-engine.ts +361 -361
- package/src/git/github-manager.ts +190 -192
- package/src/git/hook-manager.ts +210 -210
- package/src/git/index.ts +3 -3
- package/src/index.ts +7 -7
- package/src/parsers/feature-validator.ts +558 -558
- package/src/parsers/index.ts +7 -7
- package/src/parsers/parser-manager.ts +418 -419
- package/src/parsers/parser.ts +25 -25
- package/src/parsers/react-parser-optimized.ts +160 -160
- package/src/parsers/react-parser.ts +358 -358
- package/src/parsers/svelte-parser.ts +510 -510
- package/src/parsers/vanilla-parser.ts +685 -686
- package/src/parsers/vue-parser.ts +476 -478
- package/src/types/index.ts +95 -95
- package/src/ui/components.ts +567 -567
- package/src/ui/help.ts +192 -192
- package/src/ui/index.ts +3 -3
- package/src/ui/prompts.ts +680 -680
- package/src/ui/terminal-header.ts +58 -58
- package/test-build.js +40 -40
- package/test-config-commands.js +55 -55
- package/test-header-simple.js +32 -32
- package/test-terminal-header.js +11 -11
- package/test-ui.js +28 -28
- package/tests/e2e/baseguard.e2e.test.ts +515 -515
- package/tests/e2e/cross-platform.e2e.test.ts +419 -419
- package/tests/e2e/git-integration.e2e.test.ts +486 -486
- package/tests/fixtures/react-project/package.json +13 -13
- package/tests/fixtures/react-project/src/App.css +75 -75
- package/tests/fixtures/react-project/src/App.tsx +76 -76
- package/tests/fixtures/svelte-project/package.json +10 -10
- package/tests/fixtures/svelte-project/src/App.svelte +368 -368
- package/tests/fixtures/vanilla-project/index.html +75 -75
- package/tests/fixtures/vanilla-project/script.js +330 -330
- package/tests/fixtures/vanilla-project/styles.css +358 -358
- package/tests/fixtures/vue-project/package.json +11 -11
- package/tests/fixtures/vue-project/src/App.vue +215 -215
- package/tsconfig.json +34 -34
- package/vitest.config.ts +11 -11
- package/dist/terminal-header.d.ts +0 -12
- package/dist/terminal-header.js +0 -45
package/src/commands/config.ts
CHANGED
|
@@ -1,583 +1,584 @@
|
|
|
1
|
-
import { UIComponents, Prompts } from '../ui/index.js';
|
|
2
|
-
import { ConfigurationManager, ApiKeyManager, GitignoreManager } from '../core/index.js';
|
|
3
|
-
import { ConfigurationRecovery } from '../core/configuration-recovery.js';
|
|
4
|
-
import { ErrorHandler } from '../core/error-handler.js';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Manage BaseGuard configuration
|
|
9
|
-
*/
|
|
10
|
-
export async function config(action: string, options?: {
|
|
11
|
-
add?: string;
|
|
12
|
-
remove?: string;
|
|
13
|
-
preset?: string;
|
|
14
|
-
file?: string;
|
|
15
|
-
format?: string;
|
|
16
|
-
backup?: boolean;
|
|
17
|
-
interactive?: boolean;
|
|
18
|
-
agent?: string;
|
|
19
|
-
show?: boolean;
|
|
20
|
-
}): Promise<void> {
|
|
21
|
-
try {
|
|
22
|
-
switch (action) {
|
|
23
|
-
case 'show':
|
|
24
|
-
await showConfiguration();
|
|
25
|
-
break;
|
|
26
|
-
case 'list':
|
|
27
|
-
await listConfiguration(options?.format);
|
|
28
|
-
break;
|
|
29
|
-
case 'set-keys':
|
|
30
|
-
await setupApiKeys();
|
|
31
|
-
break;
|
|
32
|
-
case 'targets':
|
|
33
|
-
await updateTargets(options);
|
|
34
|
-
break;
|
|
35
|
-
case 'automation':
|
|
36
|
-
await updateAutomation();
|
|
37
|
-
break;
|
|
38
|
-
case 'update':
|
|
39
|
-
await updateConfiguration();
|
|
40
|
-
break;
|
|
41
|
-
case 'validate':
|
|
42
|
-
await validateConfiguration();
|
|
43
|
-
break;
|
|
44
|
-
case 'security':
|
|
45
|
-
await checkSecurity();
|
|
46
|
-
break;
|
|
47
|
-
case 'backup':
|
|
48
|
-
await backupConfiguration();
|
|
49
|
-
break;
|
|
50
|
-
case 'restore':
|
|
51
|
-
await restoreConfiguration(options?.file);
|
|
52
|
-
break;
|
|
53
|
-
case 'recover':
|
|
54
|
-
await recoverConfiguration(options);
|
|
55
|
-
break;
|
|
56
|
-
case 'coding-agent':
|
|
57
|
-
await manageCodingAgent(options);
|
|
58
|
-
break;
|
|
59
|
-
default:
|
|
60
|
-
UIComponents.showErrorBox(`Unknown config action: ${action}`);
|
|
61
|
-
showConfigHelp();
|
|
62
|
-
process.exit(1);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
} catch (error) {
|
|
66
|
-
const apiError = ErrorHandler.handleAPIError(error);
|
|
67
|
-
ErrorHandler.displayError(apiError);
|
|
68
|
-
|
|
69
|
-
// Provide specific help for config command issues
|
|
70
|
-
console.log('\nš” Configuration help:');
|
|
71
|
-
if (action === 'set-keys') {
|
|
72
|
-
UIComponents.showList([
|
|
73
|
-
'Get Gemini API key from https://aistudio.google.com',
|
|
74
|
-
'Get Jules API key from https://jules.google.com',
|
|
75
|
-
'Ensure API keys are valid and have proper permissions',
|
|
76
|
-
'Check your internet connection for key validation'
|
|
77
|
-
]);
|
|
78
|
-
} else if (action === 'targets') {
|
|
79
|
-
UIComponents.showList([
|
|
80
|
-
'Use format "browser version" (e.g., "chrome 100")',
|
|
81
|
-
'Available browsers: chrome, safari, firefox, edge',
|
|
82
|
-
'Use "baseline" for Baseline-only support',
|
|
83
|
-
'Check available presets with "base config targets --help"'
|
|
84
|
-
]);
|
|
85
|
-
} else if (action === 'validate') {
|
|
86
|
-
UIComponents.showList([
|
|
87
|
-
'Check .baseguardrc.json file exists',
|
|
88
|
-
'Verify JSON syntax is correct',
|
|
89
|
-
'Run "base init" to recreate configuration if needed'
|
|
90
|
-
]);
|
|
91
|
-
} else {
|
|
92
|
-
UIComponents.showList([
|
|
93
|
-
'Run "base config show" to see current configuration',
|
|
94
|
-
'Use "base config --help" to see available commands',
|
|
95
|
-
'Check file permissions in the current directory'
|
|
96
|
-
]);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
process.exit(1);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async function showConfiguration(): Promise<void> {
|
|
104
|
-
const display = await ConfigurationManager.getConfigurationDisplay();
|
|
105
|
-
|
|
106
|
-
UIComponents.showConfiguration(display.config);
|
|
107
|
-
|
|
108
|
-
// Show security status
|
|
109
|
-
if (!display.security.configIgnored) {
|
|
110
|
-
UIComponents.showWarningBox('Configuration file is not in .gitignore - API keys may be exposed!');
|
|
111
|
-
|
|
112
|
-
if (display.security.recommendations.length > 0) {
|
|
113
|
-
console.log('\nSecurity recommendations:');
|
|
114
|
-
UIComponents.showList(display.security.recommendations);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Show validation errors if any
|
|
119
|
-
if (!display.validation.valid) {
|
|
120
|
-
UIComponents.showErrorBox('Configuration validation failed');
|
|
121
|
-
UIComponents.showList(display.validation.errors);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async function listConfiguration(format?: string): Promise<void> {
|
|
126
|
-
const display = await ConfigurationManager.getConfigurationDisplay();
|
|
127
|
-
|
|
128
|
-
if (format === 'json') {
|
|
129
|
-
// Output as JSON for programmatic use
|
|
130
|
-
const output = {
|
|
131
|
-
configuration: display.config,
|
|
132
|
-
security: display.security,
|
|
133
|
-
validation: display.validation,
|
|
134
|
-
status: {
|
|
135
|
-
configured: display.config.apiKeys.jules !== null || display.config.apiKeys.gemini !== null,
|
|
136
|
-
automationEnabled: display.config.automation.enabled,
|
|
137
|
-
targetCount: display.config.targets.length
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
console.log(JSON.stringify(output, null, 2));
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Default table format
|
|
145
|
-
UIComponents.showSectionHeader('BaseGuard Configuration Summary');
|
|
146
|
-
|
|
147
|
-
// Configuration overview
|
|
148
|
-
console.log('š Configuration:');
|
|
149
|
-
console.log(` Version: ${display.config.version}`);
|
|
150
|
-
console.log(` Targets: ${display.config.targets.length} browser(s)`);
|
|
151
|
-
console.log(` API Keys: ${display.config.apiKeys.jules ? 'ā' : 'ā'} Jules, ${display.config.apiKeys.gemini ? 'ā' : 'ā'} Gemini`);
|
|
152
|
-
console.log(` Automation: ${display.config.automation.enabled ? 'ā enabled' : 'ā disabled'}`);
|
|
153
|
-
|
|
154
|
-
// Browser targets
|
|
155
|
-
console.log('\nšÆ Browser Targets:');
|
|
156
|
-
display.config.targets.forEach(target => {
|
|
157
|
-
console.log(` ⢠${target.browser} ${target.minVersion}`);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Automation settings
|
|
161
|
-
console.log('\nš¤ Automation Settings:');
|
|
162
|
-
console.log(` Enabled: ${display.config.automation.enabled ? 'ā' : 'ā'}`);
|
|
163
|
-
console.log(` Trigger: ${display.config.automation.trigger}`);
|
|
164
|
-
console.log(` Auto-analyze: ${display.config.automation.autoAnalyze ? 'ā' : 'ā'}`);
|
|
165
|
-
console.log(` Auto-fix: ${display.config.automation.autoFix ? 'ā' : 'ā'}`);
|
|
166
|
-
console.log(` Block commits: ${display.config.automation.blockCommit ? 'ā' : 'ā'}`);
|
|
167
|
-
|
|
168
|
-
// Security status
|
|
169
|
-
console.log('\nš Security Status:');
|
|
170
|
-
console.log(` .gitignore exists: ${display.security.gitignoreExists ? 'ā' : 'ā'}`);
|
|
171
|
-
console.log(` Config file ignored: ${display.security.configIgnored ? 'ā' : 'ā'}`);
|
|
172
|
-
|
|
173
|
-
// Validation status
|
|
174
|
-
console.log('\nā
Validation Status:');
|
|
175
|
-
console.log(` Configuration valid: ${display.validation.valid ? 'ā' : 'ā'}`);
|
|
176
|
-
|
|
177
|
-
// Show warnings/errors
|
|
178
|
-
if (!display.security.configIgnored) {
|
|
179
|
-
UIComponents.showWarningBox('Configuration file is not in .gitignore - API keys may be exposed!');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (!display.validation.valid) {
|
|
183
|
-
UIComponents.showErrorBox('Configuration validation failed');
|
|
184
|
-
UIComponents.showList(display.validation.errors);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (display.security.recommendations.length > 0) {
|
|
188
|
-
console.log('\nš” Recommendations:');
|
|
189
|
-
UIComponents.showList(display.security.recommendations);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async function setupApiKeys(): Promise<void> {
|
|
194
|
-
const apiKeys = await Prompts.setupApiKeys();
|
|
195
|
-
|
|
196
|
-
if (apiKeys.julesApiKey || apiKeys.geminiApiKey) {
|
|
197
|
-
await ApiKeyManager.storeApiKeys({
|
|
198
|
-
jules: apiKeys.julesApiKey,
|
|
199
|
-
gemini: apiKeys.geminiApiKey
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
UIComponents.showSuccessBox('API keys updated successfully');
|
|
203
|
-
|
|
204
|
-
// Show security reminder
|
|
205
|
-
const security = await GitignoreManager.isConfigSecure();
|
|
206
|
-
if (!security.configIgnored) {
|
|
207
|
-
UIComponents.showWarningBox('Remember to add .baseguardrc.json to .gitignore to protect your API keys');
|
|
208
|
-
}
|
|
209
|
-
} else {
|
|
210
|
-
UIComponents.showInfoBox('No API keys were configured');
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
async function updateTargets(options?: { add?: string; remove?: string; preset?: string }): Promise<void> {
|
|
215
|
-
if (options?.add) {
|
|
216
|
-
// Add a specific browser target
|
|
217
|
-
const target = ConfigurationManager.parseBrowserTarget(options.add);
|
|
218
|
-
if (!target) {
|
|
219
|
-
UIComponents.showErrorBox(`Invalid browser target format: ${options.add}`);
|
|
220
|
-
UIComponents.showInfoBox('Format: "browser version" (e.g., "chrome 100", "safari baseline")');
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
await ConfigurationManager.addBrowserTarget(target);
|
|
225
|
-
UIComponents.showSuccessBox(`Added browser target: ${target.browser} ${target.minVersion}`);
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (options?.remove) {
|
|
230
|
-
// Remove a specific browser target
|
|
231
|
-
await ConfigurationManager.removeBrowserTarget(options.remove);
|
|
232
|
-
UIComponents.showSuccessBox(`Removed browser target: ${options.remove}`);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (options?.preset) {
|
|
237
|
-
// Set preset targets
|
|
238
|
-
const presetName = options.preset as any;
|
|
239
|
-
const availablePresets = ConfigurationManager.getAvailablePresets();
|
|
240
|
-
|
|
241
|
-
if (!availablePresets.includes(presetName)) {
|
|
242
|
-
UIComponents.showErrorBox(`Invalid preset: ${options.preset}`);
|
|
243
|
-
UIComponents.showInfoBox(`Available presets: ${availablePresets.join(', ')}`);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
await ConfigurationManager.updateWithPreset(presetName);
|
|
248
|
-
UIComponents.showSuccessBox(`Updated to ${presetName} preset`);
|
|
249
|
-
UIComponents.showInfoBox(ConfigurationManager.getPresetDescription(presetName));
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Interactive target configuration
|
|
254
|
-
const targets = await Prompts.promptCustomTargets();
|
|
255
|
-
await ConfigurationManager.updateWithCustomTargets(targets);
|
|
256
|
-
UIComponents.showSuccessBox('Browser targets updated successfully');
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
async function updateAutomation(): Promise<void> {
|
|
260
|
-
const automation = await Prompts.promptAutomationSettings();
|
|
261
|
-
const config = await ConfigurationManager.load();
|
|
262
|
-
config.automation = { ...config.automation, ...automation };
|
|
263
|
-
await ConfigurationManager.save(config);
|
|
264
|
-
UIComponents.showSuccessBox('Automation settings updated successfully');
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
async function updateConfiguration(): Promise<void> {
|
|
268
|
-
const currentConfig = await ConfigurationManager.load();
|
|
269
|
-
const updates = await Prompts.promptConfigUpdate(currentConfig);
|
|
270
|
-
|
|
271
|
-
if (Object.keys(updates).length === 0) {
|
|
272
|
-
UIComponents.showInfoBox('No changes made');
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
let config = currentConfig;
|
|
277
|
-
|
|
278
|
-
// Apply updates
|
|
279
|
-
for (const [key, value] of Object.entries(updates)) {
|
|
280
|
-
switch (key) {
|
|
281
|
-
case 'targets':
|
|
282
|
-
await ConfigurationManager.updateWithCustomTargets(value as any);
|
|
283
|
-
config = await ConfigurationManager.load(); // Reload after update
|
|
284
|
-
break;
|
|
285
|
-
case 'apiKeys':
|
|
286
|
-
const apiKeys = value as any;
|
|
287
|
-
if (apiKeys.julesApiKey) config.apiKeys.jules = apiKeys.julesApiKey;
|
|
288
|
-
if (apiKeys.geminiApiKey) config.apiKeys.gemini = apiKeys.geminiApiKey;
|
|
289
|
-
break;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
UIComponents.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
console.log(`ā
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
console.log(`
|
|
394
|
-
console.log(`
|
|
395
|
-
console.log(`
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
console.log(chalk.cyan('
|
|
408
|
-
console.log(chalk.cyan(' ⢠Run "base
|
|
409
|
-
console.log(chalk.cyan(' ā¢
|
|
410
|
-
console.log(chalk.cyan(' ā¢
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
console.log(chalk.cyan('
|
|
430
|
-
console.log(chalk.cyan(' ā¢
|
|
431
|
-
console.log(chalk.cyan(' ā¢
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
UIComponents.
|
|
440
|
-
|
|
441
|
-
'base config
|
|
442
|
-
'base config list
|
|
443
|
-
'base config
|
|
444
|
-
'base config
|
|
445
|
-
'base config targets
|
|
446
|
-
'base config targets --
|
|
447
|
-
'base config targets --
|
|
448
|
-
'base config
|
|
449
|
-
'base config
|
|
450
|
-
'base config
|
|
451
|
-
'base config
|
|
452
|
-
'base config
|
|
453
|
-
'base config
|
|
454
|
-
'base config
|
|
455
|
-
'base config recover
|
|
456
|
-
'base config
|
|
457
|
-
'base config coding-agent
|
|
458
|
-
'base config coding-agent --
|
|
459
|
-
'',
|
|
460
|
-
'
|
|
461
|
-
'
|
|
462
|
-
'base
|
|
463
|
-
'base
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
console.log(
|
|
475
|
-
console.log(`
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
console.log(
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
console.log(chalk.
|
|
511
|
-
console.log(chalk.cyan('
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
console.log(chalk.
|
|
515
|
-
console.log(chalk.cyan('
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
console.log(
|
|
528
|
-
console.log(`
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
console.log(chalk.
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
{ name: '
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
{ name: '
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
config.codingAgent.
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
console.log(
|
|
567
|
-
console.log(`
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}
|
|
1
|
+
import { UIComponents, Prompts } from '../ui/index.js';
|
|
2
|
+
import { ConfigurationManager, ApiKeyManager, GitignoreManager } from '../core/index.js';
|
|
3
|
+
import { ConfigurationRecovery } from '../core/configuration-recovery.js';
|
|
4
|
+
import { ErrorHandler } from '../core/error-handler.js';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Manage BaseGuard configuration
|
|
9
|
+
*/
|
|
10
|
+
export async function config(action: string, options?: {
|
|
11
|
+
add?: string;
|
|
12
|
+
remove?: string;
|
|
13
|
+
preset?: string;
|
|
14
|
+
file?: string;
|
|
15
|
+
format?: string;
|
|
16
|
+
backup?: boolean;
|
|
17
|
+
interactive?: boolean;
|
|
18
|
+
agent?: string;
|
|
19
|
+
show?: boolean;
|
|
20
|
+
}): Promise<void> {
|
|
21
|
+
try {
|
|
22
|
+
switch (action) {
|
|
23
|
+
case 'show':
|
|
24
|
+
await showConfiguration();
|
|
25
|
+
break;
|
|
26
|
+
case 'list':
|
|
27
|
+
await listConfiguration(options?.format);
|
|
28
|
+
break;
|
|
29
|
+
case 'set-keys':
|
|
30
|
+
await setupApiKeys();
|
|
31
|
+
break;
|
|
32
|
+
case 'targets':
|
|
33
|
+
await updateTargets(options);
|
|
34
|
+
break;
|
|
35
|
+
case 'automation':
|
|
36
|
+
await updateAutomation();
|
|
37
|
+
break;
|
|
38
|
+
case 'update':
|
|
39
|
+
await updateConfiguration();
|
|
40
|
+
break;
|
|
41
|
+
case 'validate':
|
|
42
|
+
await validateConfiguration();
|
|
43
|
+
break;
|
|
44
|
+
case 'security':
|
|
45
|
+
await checkSecurity();
|
|
46
|
+
break;
|
|
47
|
+
case 'backup':
|
|
48
|
+
await backupConfiguration();
|
|
49
|
+
break;
|
|
50
|
+
case 'restore':
|
|
51
|
+
await restoreConfiguration(options?.file);
|
|
52
|
+
break;
|
|
53
|
+
case 'recover':
|
|
54
|
+
await recoverConfiguration(options);
|
|
55
|
+
break;
|
|
56
|
+
case 'coding-agent':
|
|
57
|
+
await manageCodingAgent(options);
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
UIComponents.showErrorBox(`Unknown config action: ${action}`);
|
|
61
|
+
showConfigHelp();
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const apiError = ErrorHandler.handleAPIError(error);
|
|
67
|
+
ErrorHandler.displayError(apiError);
|
|
68
|
+
|
|
69
|
+
// Provide specific help for config command issues
|
|
70
|
+
console.log('\nš” Configuration help:');
|
|
71
|
+
if (action === 'set-keys') {
|
|
72
|
+
UIComponents.showList([
|
|
73
|
+
'Get Gemini API key from https://aistudio.google.com',
|
|
74
|
+
'Get Jules API key from https://jules.google.com',
|
|
75
|
+
'Ensure API keys are valid and have proper permissions',
|
|
76
|
+
'Check your internet connection for key validation'
|
|
77
|
+
]);
|
|
78
|
+
} else if (action === 'targets') {
|
|
79
|
+
UIComponents.showList([
|
|
80
|
+
'Use format "browser version" (e.g., "chrome 100")',
|
|
81
|
+
'Available browsers: chrome, safari, firefox, edge',
|
|
82
|
+
'Use "baseline" for Baseline-only support',
|
|
83
|
+
'Check available presets with "base config targets --help"'
|
|
84
|
+
]);
|
|
85
|
+
} else if (action === 'validate') {
|
|
86
|
+
UIComponents.showList([
|
|
87
|
+
'Check .baseguardrc.json file exists',
|
|
88
|
+
'Verify JSON syntax is correct',
|
|
89
|
+
'Run "base init" to recreate configuration if needed'
|
|
90
|
+
]);
|
|
91
|
+
} else {
|
|
92
|
+
UIComponents.showList([
|
|
93
|
+
'Run "base config show" to see current configuration',
|
|
94
|
+
'Use "base config --help" to see available commands',
|
|
95
|
+
'Check file permissions in the current directory'
|
|
96
|
+
]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function showConfiguration(): Promise<void> {
|
|
104
|
+
const display = await ConfigurationManager.getConfigurationDisplay();
|
|
105
|
+
|
|
106
|
+
UIComponents.showConfiguration(display.config);
|
|
107
|
+
|
|
108
|
+
// Show security status
|
|
109
|
+
if (!display.security.configIgnored) {
|
|
110
|
+
UIComponents.showWarningBox('Configuration file is not in .gitignore - API keys may be exposed!');
|
|
111
|
+
|
|
112
|
+
if (display.security.recommendations.length > 0) {
|
|
113
|
+
console.log('\nSecurity recommendations:');
|
|
114
|
+
UIComponents.showList(display.security.recommendations);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Show validation errors if any
|
|
119
|
+
if (!display.validation.valid) {
|
|
120
|
+
UIComponents.showErrorBox('Configuration validation failed');
|
|
121
|
+
UIComponents.showList(display.validation.errors);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function listConfiguration(format?: string): Promise<void> {
|
|
126
|
+
const display = await ConfigurationManager.getConfigurationDisplay();
|
|
127
|
+
|
|
128
|
+
if (format === 'json') {
|
|
129
|
+
// Output as JSON for programmatic use
|
|
130
|
+
const output = {
|
|
131
|
+
configuration: display.config,
|
|
132
|
+
security: display.security,
|
|
133
|
+
validation: display.validation,
|
|
134
|
+
status: {
|
|
135
|
+
configured: display.config.apiKeys.jules !== null || display.config.apiKeys.gemini !== null,
|
|
136
|
+
automationEnabled: display.config.automation.enabled,
|
|
137
|
+
targetCount: display.config.targets.length
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
console.log(JSON.stringify(output, null, 2));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Default table format
|
|
145
|
+
UIComponents.showSectionHeader('BaseGuard Configuration Summary');
|
|
146
|
+
|
|
147
|
+
// Configuration overview
|
|
148
|
+
console.log('š Configuration:');
|
|
149
|
+
console.log(` Version: ${display.config.version}`);
|
|
150
|
+
console.log(` Targets: ${display.config.targets.length} browser(s)`);
|
|
151
|
+
console.log(` API Keys: ${display.config.apiKeys.jules ? 'ā' : 'ā'} Jules, ${display.config.apiKeys.gemini ? 'ā' : 'ā'} Gemini`);
|
|
152
|
+
console.log(` Automation: ${display.config.automation.enabled ? 'ā enabled' : 'ā disabled'}`);
|
|
153
|
+
|
|
154
|
+
// Browser targets
|
|
155
|
+
console.log('\nšÆ Browser Targets:');
|
|
156
|
+
display.config.targets.forEach(target => {
|
|
157
|
+
console.log(` ⢠${target.browser} ${target.minVersion}`);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// Automation settings
|
|
161
|
+
console.log('\nš¤ Automation Settings:');
|
|
162
|
+
console.log(` Enabled: ${display.config.automation.enabled ? 'ā' : 'ā'}`);
|
|
163
|
+
console.log(` Trigger: ${display.config.automation.trigger}`);
|
|
164
|
+
console.log(` Auto-analyze: ${display.config.automation.autoAnalyze ? 'ā' : 'ā'}`);
|
|
165
|
+
console.log(` Auto-fix: ${display.config.automation.autoFix ? 'ā' : 'ā'}`);
|
|
166
|
+
console.log(` Block commits: ${display.config.automation.blockCommit ? 'ā' : 'ā'}`);
|
|
167
|
+
|
|
168
|
+
// Security status
|
|
169
|
+
console.log('\nš Security Status:');
|
|
170
|
+
console.log(` .gitignore exists: ${display.security.gitignoreExists ? 'ā' : 'ā'}`);
|
|
171
|
+
console.log(` Config file ignored: ${display.security.configIgnored ? 'ā' : 'ā'}`);
|
|
172
|
+
|
|
173
|
+
// Validation status
|
|
174
|
+
console.log('\nā
Validation Status:');
|
|
175
|
+
console.log(` Configuration valid: ${display.validation.valid ? 'ā' : 'ā'}`);
|
|
176
|
+
|
|
177
|
+
// Show warnings/errors
|
|
178
|
+
if (!display.security.configIgnored) {
|
|
179
|
+
UIComponents.showWarningBox('Configuration file is not in .gitignore - API keys may be exposed!');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (!display.validation.valid) {
|
|
183
|
+
UIComponents.showErrorBox('Configuration validation failed');
|
|
184
|
+
UIComponents.showList(display.validation.errors);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (display.security.recommendations.length > 0) {
|
|
188
|
+
console.log('\nš” Recommendations:');
|
|
189
|
+
UIComponents.showList(display.security.recommendations);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function setupApiKeys(): Promise<void> {
|
|
194
|
+
const apiKeys = await Prompts.setupApiKeys();
|
|
195
|
+
|
|
196
|
+
if (apiKeys.julesApiKey || apiKeys.geminiApiKey) {
|
|
197
|
+
await ApiKeyManager.storeApiKeys({
|
|
198
|
+
jules: apiKeys.julesApiKey,
|
|
199
|
+
gemini: apiKeys.geminiApiKey
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
UIComponents.showSuccessBox('API keys updated successfully');
|
|
203
|
+
|
|
204
|
+
// Show security reminder
|
|
205
|
+
const security = await GitignoreManager.isConfigSecure();
|
|
206
|
+
if (!security.configIgnored) {
|
|
207
|
+
UIComponents.showWarningBox('Remember to add .baseguardrc.json to .gitignore to protect your API keys');
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
UIComponents.showInfoBox('No API keys were configured');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function updateTargets(options?: { add?: string; remove?: string; preset?: string }): Promise<void> {
|
|
215
|
+
if (options?.add) {
|
|
216
|
+
// Add a specific browser target
|
|
217
|
+
const target = ConfigurationManager.parseBrowserTarget(options.add);
|
|
218
|
+
if (!target) {
|
|
219
|
+
UIComponents.showErrorBox(`Invalid browser target format: ${options.add}`);
|
|
220
|
+
UIComponents.showInfoBox('Format: "browser version" (e.g., "chrome 100", "safari baseline")');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
await ConfigurationManager.addBrowserTarget(target);
|
|
225
|
+
UIComponents.showSuccessBox(`Added browser target: ${target.browser} ${target.minVersion}`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (options?.remove) {
|
|
230
|
+
// Remove a specific browser target
|
|
231
|
+
await ConfigurationManager.removeBrowserTarget(options.remove);
|
|
232
|
+
UIComponents.showSuccessBox(`Removed browser target: ${options.remove}`);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (options?.preset) {
|
|
237
|
+
// Set preset targets
|
|
238
|
+
const presetName = options.preset as any;
|
|
239
|
+
const availablePresets = ConfigurationManager.getAvailablePresets();
|
|
240
|
+
|
|
241
|
+
if (!availablePresets.includes(presetName)) {
|
|
242
|
+
UIComponents.showErrorBox(`Invalid preset: ${options.preset}`);
|
|
243
|
+
UIComponents.showInfoBox(`Available presets: ${availablePresets.join(', ')}`);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
await ConfigurationManager.updateWithPreset(presetName);
|
|
248
|
+
UIComponents.showSuccessBox(`Updated to ${presetName} preset`);
|
|
249
|
+
UIComponents.showInfoBox(ConfigurationManager.getPresetDescription(presetName));
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Interactive target configuration
|
|
254
|
+
const targets = await Prompts.promptCustomTargets();
|
|
255
|
+
await ConfigurationManager.updateWithCustomTargets(targets);
|
|
256
|
+
UIComponents.showSuccessBox('Browser targets updated successfully');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function updateAutomation(): Promise<void> {
|
|
260
|
+
const automation = await Prompts.promptAutomationSettings();
|
|
261
|
+
const config = await ConfigurationManager.load();
|
|
262
|
+
config.automation = { ...config.automation, ...automation };
|
|
263
|
+
await ConfigurationManager.save(config);
|
|
264
|
+
UIComponents.showSuccessBox('Automation settings updated successfully');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async function updateConfiguration(): Promise<void> {
|
|
268
|
+
const currentConfig = await ConfigurationManager.load();
|
|
269
|
+
const updates = await Prompts.promptConfigUpdate(currentConfig);
|
|
270
|
+
|
|
271
|
+
if (Object.keys(updates).length === 0) {
|
|
272
|
+
UIComponents.showInfoBox('No changes made');
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
let config = currentConfig;
|
|
277
|
+
|
|
278
|
+
// Apply updates
|
|
279
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
280
|
+
switch (key) {
|
|
281
|
+
case 'targets':
|
|
282
|
+
await ConfigurationManager.updateWithCustomTargets(value as any);
|
|
283
|
+
config = await ConfigurationManager.load(); // Reload after update
|
|
284
|
+
break;
|
|
285
|
+
case 'apiKeys': {
|
|
286
|
+
const apiKeys = value as any;
|
|
287
|
+
if (apiKeys.julesApiKey) config.apiKeys.jules = apiKeys.julesApiKey;
|
|
288
|
+
if (apiKeys.geminiApiKey) config.apiKeys.gemini = apiKeys.geminiApiKey;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case 'automation':
|
|
292
|
+
config.automation = { ...config.automation, ...(value as any) };
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
await ConfigurationManager.save(config);
|
|
298
|
+
UIComponents.showSuccessBox('Configuration updated successfully');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async function validateConfiguration(): Promise<void> {
|
|
302
|
+
const display = await ConfigurationManager.getConfigurationDisplay();
|
|
303
|
+
|
|
304
|
+
if (display.validation.valid) {
|
|
305
|
+
UIComponents.showSuccessBox('Configuration is valid');
|
|
306
|
+
} else {
|
|
307
|
+
UIComponents.showErrorBox('Configuration validation failed');
|
|
308
|
+
UIComponents.showList(display.validation.errors);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async function checkSecurity(): Promise<void> {
|
|
314
|
+
const security = await GitignoreManager.isConfigSecure();
|
|
315
|
+
|
|
316
|
+
UIComponents.showSectionHeader('Security Status');
|
|
317
|
+
|
|
318
|
+
console.log(`ā .gitignore exists: ${security.gitignoreExists ? 'Yes' : 'No'}`);
|
|
319
|
+
console.log(`ā Config file ignored: ${security.configIgnored ? 'Yes' : 'No'}`);
|
|
320
|
+
|
|
321
|
+
if (security.recommendations.length > 0) {
|
|
322
|
+
console.log('\nRecommendations:');
|
|
323
|
+
UIComponents.showList(security.recommendations);
|
|
324
|
+
} else {
|
|
325
|
+
UIComponents.showSuccessBox('Configuration is secure');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async function backupConfiguration(): Promise<void> {
|
|
330
|
+
try {
|
|
331
|
+
const backupFile = await ConfigurationManager.backupConfiguration();
|
|
332
|
+
UIComponents.showSuccessBox(`Configuration backed up to: ${backupFile}`);
|
|
333
|
+
} catch (error) {
|
|
334
|
+
UIComponents.showErrorBox(`Backup failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async function restoreConfiguration(backupFile?: string): Promise<void> {
|
|
340
|
+
if (!backupFile) {
|
|
341
|
+
UIComponents.showErrorBox('Backup file path is required');
|
|
342
|
+
console.log('Usage: base config restore --file <backup-file>');
|
|
343
|
+
process.exit(1);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
await ConfigurationManager.restoreConfiguration(backupFile);
|
|
348
|
+
UIComponents.showSuccessBox('Configuration restored successfully');
|
|
349
|
+
} catch (error) {
|
|
350
|
+
UIComponents.showErrorBox(`Restore failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
async function recoverConfiguration(options?: { backup?: boolean; interactive?: boolean }): Promise<void> {
|
|
356
|
+
try {
|
|
357
|
+
console.log(chalk.cyan('š§ BaseGuard Configuration Recovery\n'));
|
|
358
|
+
|
|
359
|
+
if (options?.interactive) {
|
|
360
|
+
// Run interactive recovery wizard
|
|
361
|
+
await ConfigurationRecovery.runRecoveryWizard();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Automatic recovery
|
|
366
|
+
console.log(chalk.cyan('Attempting automatic configuration recovery...'));
|
|
367
|
+
|
|
368
|
+
const recoveryResult = await ConfigurationRecovery.recoverConfiguration({
|
|
369
|
+
createBackup: options?.backup ?? true,
|
|
370
|
+
validateConfig: true,
|
|
371
|
+
migrateVersion: true,
|
|
372
|
+
repairCorruption: true,
|
|
373
|
+
useDefaults: true
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
if (recoveryResult.success) {
|
|
377
|
+
UIComponents.showSuccessBox('Configuration recovered successfully');
|
|
378
|
+
|
|
379
|
+
if (recoveryResult.backupCreated) {
|
|
380
|
+
console.log(chalk.dim(`Backup created: ${recoveryResult.backupCreated}`));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (recoveryResult.warnings.length > 0) {
|
|
384
|
+
console.log(chalk.yellow('\nā ļø Recovery warnings:'));
|
|
385
|
+
recoveryResult.warnings.forEach(warning => {
|
|
386
|
+
console.log(chalk.yellow(` ⢠${warning}`));
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Show recovered configuration
|
|
391
|
+
console.log(chalk.cyan('\nš Recovered Configuration:'));
|
|
392
|
+
if (recoveryResult.config) {
|
|
393
|
+
console.log(` Version: ${recoveryResult.config.version}`);
|
|
394
|
+
console.log(` Targets: ${recoveryResult.config.targets.length} browser(s)`);
|
|
395
|
+
console.log(` API Keys: Jules ${recoveryResult.config.apiKeys.jules ? 'ā' : 'ā'}, Gemini ${recoveryResult.config.apiKeys.gemini ? 'ā' : 'ā'}`);
|
|
396
|
+
console.log(` Automation: ${recoveryResult.config.automation.enabled ? 'Enabled' : 'Disabled'}`);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
} else {
|
|
400
|
+
UIComponents.showErrorBox('Configuration recovery failed');
|
|
401
|
+
|
|
402
|
+
console.log(chalk.red('\nā Recovery errors:'));
|
|
403
|
+
recoveryResult.errors.forEach(error => {
|
|
404
|
+
console.log(chalk.red(` ⢠${error}`));
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
console.log(chalk.cyan('\nš” Manual recovery options:'));
|
|
408
|
+
console.log(chalk.cyan(' ⢠Run "base config recover --interactive" for guided recovery'));
|
|
409
|
+
console.log(chalk.cyan(' ⢠Run "base init" to create a fresh configuration'));
|
|
410
|
+
console.log(chalk.cyan(' ⢠Manually edit .baseguardrc.json file'));
|
|
411
|
+
console.log(chalk.cyan(' ⢠Restore from backup if available'));
|
|
412
|
+
|
|
413
|
+
// Show available backups
|
|
414
|
+
const backups = await ConfigurationRecovery.listBackups();
|
|
415
|
+
if (backups.length > 0) {
|
|
416
|
+
console.log(chalk.cyan('\nš¦ Available backups:'));
|
|
417
|
+
backups.slice(0, 3).forEach(backup => {
|
|
418
|
+
console.log(chalk.cyan(` ⢠${backup.timestamp.toLocaleString()} (${backup.source})`));
|
|
419
|
+
});
|
|
420
|
+
console.log(chalk.cyan('\n Use "base config restore --file <backup-file>" to restore'));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
process.exit(1);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
} catch (error) {
|
|
427
|
+
UIComponents.showErrorBox(`Recovery process failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
428
|
+
|
|
429
|
+
console.log(chalk.cyan('\nš Emergency recovery options:'));
|
|
430
|
+
console.log(chalk.cyan(' ⢠Delete .baseguardrc.json and run "base init"'));
|
|
431
|
+
console.log(chalk.cyan(' ⢠Check file permissions in your project directory'));
|
|
432
|
+
console.log(chalk.cyan(' ⢠Run "base diagnostics" for comprehensive troubleshooting'));
|
|
433
|
+
|
|
434
|
+
process.exit(1);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function showConfigHelp(): void {
|
|
439
|
+
UIComponents.showSectionHeader('Configuration Commands');
|
|
440
|
+
UIComponents.showList([
|
|
441
|
+
'base config show - Display current configuration',
|
|
442
|
+
'base config list - List configuration summary',
|
|
443
|
+
'base config list --format json - List configuration as JSON',
|
|
444
|
+
'base config set-keys - Set up API keys for AI services',
|
|
445
|
+
'base config targets - Configure browser targets',
|
|
446
|
+
'base config targets --add "chrome 100" - Add browser target',
|
|
447
|
+
'base config targets --remove chrome - Remove browser target',
|
|
448
|
+
'base config targets --preset baseline-widely - Set preset targets',
|
|
449
|
+
'base config automation - Configure git automation',
|
|
450
|
+
'base config update - Interactive configuration update',
|
|
451
|
+
'base config validate - Validate configuration file',
|
|
452
|
+
'base config security - Check configuration security',
|
|
453
|
+
'base config backup - Create configuration backup',
|
|
454
|
+
'base config restore --file <backup> - Restore from backup',
|
|
455
|
+
'base config recover - Attempt automatic configuration recovery',
|
|
456
|
+
'base config recover --interactive - Run interactive recovery wizard',
|
|
457
|
+
'base config coding-agent - Manage coding agent selection (Jules vs Gemini)',
|
|
458
|
+
'base config coding-agent --show - Show current agent configuration',
|
|
459
|
+
'base config coding-agent --agent gemini - Set Gemini as primary agent',
|
|
460
|
+
'',
|
|
461
|
+
'Shorthand commands:',
|
|
462
|
+
'base add "chrome 100" - Add browser target',
|
|
463
|
+
'base remove chrome - Remove browser target',
|
|
464
|
+
'base list - List configuration summary'
|
|
465
|
+
]);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
async function manageCodingAgent(options?: { agent?: string; show?: boolean }): Promise<void> {
|
|
469
|
+
try {
|
|
470
|
+
const config = await ConfigurationManager.load();
|
|
471
|
+
|
|
472
|
+
if (options?.show) {
|
|
473
|
+
// Show current coding agent configuration
|
|
474
|
+
console.log(chalk.cyan('š¤ Coding Agent Configuration\n'));
|
|
475
|
+
console.log(`Primary Agent: ${chalk.white(config.codingAgent.primary)}`);
|
|
476
|
+
console.log(`Fallback Agent: ${chalk.white(config.codingAgent.fallback)}`);
|
|
477
|
+
|
|
478
|
+
// Show agent status
|
|
479
|
+
const { UnifiedCodeFixer } = await import('../ai/unified-code-fixer.js');
|
|
480
|
+
const unifiedFixer = new UnifiedCodeFixer(config);
|
|
481
|
+
const status = await unifiedFixer.getAgentStatus();
|
|
482
|
+
|
|
483
|
+
console.log(chalk.cyan('\nš Agent Status:'));
|
|
484
|
+
console.log(`Jules: ${status.jules.configured ? 'š' : 'ā'} configured, ${status.jules.available ? 'ā
' : 'ā'} available`);
|
|
485
|
+
if (status.jules.repoDetected !== undefined) {
|
|
486
|
+
console.log(` ${status.jules.repoDetected ? 'ā
' : 'ā'} GitHub repository detected`);
|
|
487
|
+
}
|
|
488
|
+
console.log(`Gemini: ${status.gemini.configured ? 'š' : 'ā'} configured, ${status.gemini.available ? 'ā
' : 'ā'} available`);
|
|
489
|
+
|
|
490
|
+
// Show comparison
|
|
491
|
+
unifiedFixer.showAgentComparison();
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (options?.agent) {
|
|
496
|
+
// Set specific agent
|
|
497
|
+
const agent = options.agent.toLowerCase();
|
|
498
|
+
if (agent !== 'jules' && agent !== 'gemini') {
|
|
499
|
+
UIComponents.showErrorBox('Invalid agent. Use "jules" or "gemini"');
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
config.codingAgent.primary = agent as 'jules' | 'gemini';
|
|
504
|
+
await ConfigurationManager.save(config);
|
|
505
|
+
|
|
506
|
+
console.log(chalk.green(`ā
Primary coding agent set to ${agent}`));
|
|
507
|
+
|
|
508
|
+
// Show setup instructions if API key is missing
|
|
509
|
+
if (agent === 'jules' && !config.apiKeys.jules) {
|
|
510
|
+
console.log(chalk.yellow('\nā ļø Jules API key not configured'));
|
|
511
|
+
console.log(chalk.cyan('Get your Jules API key: https://jules.google.com/settings#api'));
|
|
512
|
+
console.log(chalk.cyan('Run "base config set-keys" to configure it'));
|
|
513
|
+
} else if (agent === 'gemini' && !config.apiKeys.gemini) {
|
|
514
|
+
console.log(chalk.yellow('\nā ļø Gemini API key not configured'));
|
|
515
|
+
console.log(chalk.cyan('Get your Gemini API key: https://aistudio.google.com'));
|
|
516
|
+
console.log(chalk.cyan('Run "base config set-keys" to configure it'));
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Interactive agent selection
|
|
523
|
+
const { UnifiedCodeFixer } = await import('../ai/unified-code-fixer.js');
|
|
524
|
+
const unifiedFixer = new UnifiedCodeFixer(config);
|
|
525
|
+
|
|
526
|
+
// Show current status
|
|
527
|
+
console.log(chalk.cyan('š¤ Current Coding Agent Configuration\n'));
|
|
528
|
+
console.log(`Primary: ${config.codingAgent.primary}`);
|
|
529
|
+
console.log(`Fallback: ${config.codingAgent.fallback}`);
|
|
530
|
+
|
|
531
|
+
// Get recommendation
|
|
532
|
+
const recommendation = await unifiedFixer.getRecommendedAgent();
|
|
533
|
+
console.log(chalk.cyan(`\nš” Recommended: ${recommendation.agent}`));
|
|
534
|
+
console.log(chalk.dim(` Reason: ${recommendation.reason}`));
|
|
535
|
+
|
|
536
|
+
// Interactive selection
|
|
537
|
+
const { default: inquirer } = await import('inquirer');
|
|
538
|
+
const answers = await inquirer.prompt([
|
|
539
|
+
{
|
|
540
|
+
type: 'list',
|
|
541
|
+
name: 'primary',
|
|
542
|
+
message: 'Select primary coding agent:',
|
|
543
|
+
choices: [
|
|
544
|
+
{ name: 'Gemini 2.5 Pro (works with any files, immediate)', value: 'gemini' },
|
|
545
|
+
{ name: 'Jules (GitHub repos only, autonomous)', value: 'jules' }
|
|
546
|
+
],
|
|
547
|
+
default: recommendation.agent
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
type: 'list',
|
|
551
|
+
name: 'fallback',
|
|
552
|
+
message: 'Select fallback coding agent:',
|
|
553
|
+
choices: [
|
|
554
|
+
{ name: 'Gemini 2.5 Pro', value: 'gemini' },
|
|
555
|
+
{ name: 'Jules', value: 'jules' }
|
|
556
|
+
],
|
|
557
|
+
default: 'gemini'
|
|
558
|
+
}
|
|
559
|
+
]);
|
|
560
|
+
|
|
561
|
+
config.codingAgent.primary = answers.primary;
|
|
562
|
+
config.codingAgent.fallback = answers.fallback;
|
|
563
|
+
|
|
564
|
+
await ConfigurationManager.save(config);
|
|
565
|
+
|
|
566
|
+
console.log(chalk.green('\nā
Coding agent configuration updated'));
|
|
567
|
+
console.log(`Primary: ${answers.primary}`);
|
|
568
|
+
console.log(`Fallback: ${answers.fallback}`);
|
|
569
|
+
|
|
570
|
+
// Show next steps
|
|
571
|
+
console.log(chalk.cyan('\nš§ Next Steps:'));
|
|
572
|
+
if (!config.apiKeys[answers.primary as keyof typeof config.apiKeys]) {
|
|
573
|
+
console.log(chalk.cyan(`⢠Configure ${answers.primary} API key: "base config set-keys"`));
|
|
574
|
+
}
|
|
575
|
+
if (answers.primary !== answers.fallback && !config.apiKeys[answers.fallback as keyof typeof config.apiKeys]) {
|
|
576
|
+
console.log(chalk.cyan(`⢠Configure ${answers.fallback} API key for fallback: "base config set-keys"`));
|
|
577
|
+
}
|
|
578
|
+
console.log(chalk.cyan('⢠Test with: "base fix --analyze-only"'));
|
|
579
|
+
|
|
580
|
+
} catch (error) {
|
|
581
|
+
UIComponents.showErrorBox(`Failed to manage coding agent: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
582
|
+
process.exit(1);
|
|
583
|
+
}
|
|
584
|
+
}
|