ai-changelog-generator-extension 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,333 @@
1
+ import * as vscode from 'vscode'
2
+ import { ExtensionConfigurationManager } from '../services/ExtensionConfigurationManager'
3
+ import { EnvFileService } from '../services/EnvFileService'
4
+ import { StatusService } from '../services/StatusService'
5
+
6
+ export async function setupWizard(
7
+ configManager: ExtensionConfigurationManager
8
+ ): Promise<boolean> {
9
+ const config = vscode.workspace.getConfiguration('aiChangelog')
10
+
11
+ StatusService.log('Setup wizard started')
12
+
13
+ // Welcome message
14
+ const proceed = await vscode.window.showInformationMessage(
15
+ '🎉 Welcome to AI Changelog Generator!\n\nThis wizard will help you configure your AI provider in 3 simple steps:\n\n1️⃣ Choose storage method\n2️⃣ Select AI provider\n3️⃣ Enter credentials\n\nReady to begin?',
16
+ { modal: true },
17
+ 'Start Setup',
18
+ 'Cancel'
19
+ )
20
+
21
+ if (proceed !== 'Start Setup') {
22
+ StatusService.log('Setup wizard cancelled by user')
23
+ return false
24
+ }
25
+
26
+ try {
27
+ // Step 1: Check for existing environment variables
28
+ const autoDetect = config.get<boolean>('autoDetectEnv', true)
29
+ if (autoDetect) {
30
+ const envVars = await EnvFileService.detectEnvironmentVariables()
31
+ if (Object.keys(envVars).length > 0) {
32
+ StatusService.log(`Found ${Object.keys(envVars).length} API keys in .env files`)
33
+
34
+ const useEnv = await vscode.window.showInformationMessage(
35
+ `🔍 Found API keys in .env file!\n\nDetected: ${Object.keys(envVars).join(', ')}\n\nWould you like to import these keys?`,
36
+ { modal: true },
37
+ 'Import from .env',
38
+ 'Configure Manually'
39
+ )
40
+
41
+ if (useEnv === 'Import from .env') {
42
+ StatusService.log('Importing keys from .env file...')
43
+
44
+ // Import keys from .env
45
+ for (const [key, value] of Object.entries(envVars)) {
46
+ const provider = EnvFileService.getProviderFromKey(key)
47
+ if (provider && value) {
48
+ await configManager.storeApiKey(provider, value)
49
+ StatusService.log(`✓ Imported ${key} for ${provider}`)
50
+ }
51
+ }
52
+
53
+ // Set storage mode to env
54
+ await config.update('storageMode', 'env', vscode.ConfigurationTarget.Workspace)
55
+
56
+ // Determine primary provider
57
+ const firstKey = Object.keys(envVars)[0]
58
+ const primaryProvider = EnvFileService.getProviderFromKey(firstKey)
59
+ if (primaryProvider) {
60
+ await config.update('provider', primaryProvider, vscode.ConfigurationTarget.Workspace)
61
+ StatusService.log(`Set primary provider to ${primaryProvider}`)
62
+ }
63
+
64
+ await config.update('setupCompleted', true, vscode.ConfigurationTarget.Workspace)
65
+
66
+ vscode.window.showInformationMessage(
67
+ '✅ Setup complete! API keys imported from .env file.',
68
+ 'Test Connection'
69
+ ).then((action) => {
70
+ if (action === 'Test Connection') {
71
+ vscode.commands.executeCommand('ai-changelog.testConnection')
72
+ }
73
+ })
74
+
75
+ StatusService.log('Setup completed successfully (env import)')
76
+ return true
77
+ }
78
+ }
79
+ }
80
+
81
+ // Step 2: Choose storage mode
82
+ await vscode.window.showInformationMessage(
83
+ '📍 Step 1 of 3: Storage Method\n\nWhere should API keys be stored?',
84
+ { modal: false }
85
+ )
86
+
87
+ const storageMode = await vscode.window.showQuickPick(
88
+ [
89
+ {
90
+ label: '🔒 Secure Storage (Recommended)',
91
+ description: 'Store keys in VS Code secret storage',
92
+ value: 'secrets',
93
+ },
94
+ {
95
+ label: '📄 Environment File',
96
+ description: 'Store keys in .env.local file',
97
+ value: 'env',
98
+ },
99
+ {
100
+ label: '⚙️ Settings File',
101
+ description: 'Store in settings.json (not recommended - not secure)',
102
+ value: 'settings',
103
+ },
104
+ ],
105
+ {
106
+ placeHolder: 'Select where to store API keys',
107
+ ignoreFocusOut: true,
108
+ }
109
+ )
110
+
111
+ if (!storageMode) {
112
+ StatusService.log('Setup cancelled: No storage mode selected')
113
+ return false
114
+ }
115
+
116
+ await config.update('storageMode', storageMode.value, vscode.ConfigurationTarget.Workspace)
117
+ StatusService.log(`Storage mode set to: ${storageMode.value}`)
118
+
119
+ // Step 3: Choose provider
120
+ await vscode.window.showInformationMessage(
121
+ '📍 Step 2 of 3: AI Provider\n\nSelect your AI provider',
122
+ { modal: false }
123
+ )
124
+
125
+ const provider = await vscode.window.showQuickPick(
126
+ [
127
+ { label: 'OpenAI', description: 'GPT-4, GPT-4 Turbo, GPT-4o', value: 'openai' },
128
+ { label: 'Anthropic', description: 'Claude 3.5 Sonnet, Opus', value: 'anthropic' },
129
+ { label: 'Google', description: 'Gemini Pro, Gemini Ultra', value: 'google' },
130
+ { label: 'Azure OpenAI', description: 'Azure-hosted OpenAI models', value: 'azure' },
131
+ {
132
+ label: 'AWS Bedrock',
133
+ description: 'Claude via AWS Bedrock',
134
+ value: 'bedrock',
135
+ },
136
+ { label: 'Ollama', description: 'Local models via Ollama', value: 'ollama' },
137
+ { label: 'LM Studio', description: 'Local models via LM Studio', value: 'lmstudio' },
138
+ ],
139
+ {
140
+ placeHolder: 'Select your AI provider',
141
+ ignoreFocusOut: true,
142
+ }
143
+ )
144
+
145
+ if (!provider) {
146
+ StatusService.log('Setup cancelled: No provider selected')
147
+ return false
148
+ }
149
+
150
+ await config.update('provider', provider.value, vscode.ConfigurationTarget.Workspace)
151
+ StatusService.log(`Provider set to: ${provider.value}`)
152
+
153
+ // Step 4: Configure provider-specific settings
154
+ await vscode.window.showInformationMessage(
155
+ `📍 Step 3 of 3: Configure ${provider.label}\n\nAlmost there!`,
156
+ { modal: false }
157
+ )
158
+
159
+ // Handle local providers (Ollama, LM Studio)
160
+ if (provider.value === 'ollama') {
161
+ const host = await vscode.window.showInputBox({
162
+ prompt: 'Ollama API host',
163
+ value: 'http://localhost:11434',
164
+ placeHolder: 'http://localhost:11434',
165
+ ignoreFocusOut: true,
166
+ })
167
+
168
+ if (host) {
169
+ await config.update('ollamaHost', host, vscode.ConfigurationTarget.Workspace)
170
+ }
171
+
172
+ const model = await vscode.window.showInputBox({
173
+ prompt: 'Ollama model name',
174
+ value: 'mistral',
175
+ placeHolder: 'mistral',
176
+ ignoreFocusOut: true,
177
+ })
178
+
179
+ if (model) {
180
+ await config.update('model', model, vscode.ConfigurationTarget.Workspace)
181
+ }
182
+
183
+ await config.update('setupCompleted', true, vscode.ConfigurationTarget.Workspace)
184
+ StatusService.log('Setup completed successfully (Ollama)')
185
+
186
+ const testNow = await vscode.window.showInformationMessage(
187
+ '✅ Ollama configured successfully!\n\nWould you like to test the connection?',
188
+ 'Test Now',
189
+ 'Skip'
190
+ )
191
+
192
+ if (testNow === 'Test Now') {
193
+ vscode.commands.executeCommand('ai-changelog.testConnection')
194
+ }
195
+
196
+ return true
197
+ }
198
+
199
+ if (provider.value === 'lmstudio') {
200
+ const host = await vscode.window.showInputBox({
201
+ prompt: 'LM Studio API host',
202
+ value: 'http://localhost:1234',
203
+ placeHolder: 'http://localhost:1234',
204
+ ignoreFocusOut: true,
205
+ })
206
+
207
+ if (host) {
208
+ await config.update('lmStudioHost', host, vscode.ConfigurationTarget.Workspace)
209
+ }
210
+
211
+ await config.update('setupCompleted', true, vscode.ConfigurationTarget.Workspace)
212
+ StatusService.log('Setup completed successfully (LM Studio)')
213
+
214
+ const testNow = await vscode.window.showInformationMessage(
215
+ '✅ LM Studio configured successfully!\n\nWould you like to test the connection?',
216
+ 'Test Now',
217
+ 'Skip'
218
+ )
219
+
220
+ if (testNow === 'Test Now') {
221
+ vscode.commands.executeCommand('ai-changelog.testConnection')
222
+ }
223
+
224
+ return true
225
+ }
226
+
227
+ // Step 5: Get API key for cloud providers
228
+ const apiKey = await vscode.window.showInputBox({
229
+ prompt: `Enter your ${provider.label} API key`,
230
+ password: true,
231
+ placeHolder: 'sk-...',
232
+ ignoreFocusOut: true,
233
+ validateInput: (value) => {
234
+ if (!value || value.trim().length === 0) {
235
+ return 'API key is required'
236
+ }
237
+ if (value.length < 10) {
238
+ return 'API key seems too short. Please check it.'
239
+ }
240
+ return null
241
+ },
242
+ })
243
+
244
+ if (!apiKey) {
245
+ StatusService.log('Setup cancelled: No API key entered')
246
+ return false
247
+ }
248
+
249
+ StatusService.log(`API key entered for ${provider.value} (${apiKey.length} characters)`)
250
+
251
+ // Step 6: Save API key based on storage mode
252
+ try {
253
+ if (storageMode.value === 'env') {
254
+ const keyName = configManager['getKeyNameForProvider'](provider.value)
255
+ await EnvFileService.saveToEnvFile(keyName, apiKey)
256
+ StatusService.log(`✓ API key saved to .env file`)
257
+ vscode.window.showInformationMessage(`✅ API key saved to .env.local`)
258
+ } else if (storageMode.value === 'settings') {
259
+ // Save to workspace settings (not recommended)
260
+ const keyName = `${provider.value}ApiKey`
261
+ await config.update(keyName, apiKey, vscode.ConfigurationTarget.Workspace)
262
+ StatusService.log(`✓ API key saved to settings.json`)
263
+ vscode.window.showWarningMessage(
264
+ '⚠️ API key stored in settings.json. This is visible in your workspace settings and not recommended for security.'
265
+ )
266
+ } else {
267
+ // Default: secure storage
268
+ await configManager.storeApiKey(provider.value, apiKey)
269
+ StatusService.log(`✓ API key saved to secure storage`)
270
+ }
271
+ } catch (error) {
272
+ const errorMsg = error instanceof Error ? error.message : String(error)
273
+ StatusService.log(`✗ Failed to save API key: ${errorMsg}`)
274
+ vscode.window.showErrorMessage(`Failed to save API key: ${errorMsg}`)
275
+ return false
276
+ }
277
+
278
+ // Azure-specific configuration
279
+ if (provider.value === 'azure') {
280
+ const endpoint = await vscode.window.showInputBox({
281
+ prompt: 'Azure OpenAI endpoint',
282
+ placeHolder: 'https://your-resource.openai.azure.com',
283
+ ignoreFocusOut: true,
284
+ })
285
+
286
+ if (endpoint) {
287
+ await config.update('azureEndpoint', endpoint, vscode.ConfigurationTarget.Workspace)
288
+ }
289
+
290
+ const deployment = await vscode.window.showInputBox({
291
+ prompt: 'Azure deployment name',
292
+ placeHolder: 'gpt-4',
293
+ ignoreFocusOut: true,
294
+ })
295
+
296
+ if (deployment) {
297
+ await config.update(
298
+ 'azureDeploymentName',
299
+ deployment,
300
+ vscode.ConfigurationTarget.Workspace
301
+ )
302
+ }
303
+ }
304
+
305
+ // Mark setup as completed
306
+ await config.update('setupCompleted', true, vscode.ConfigurationTarget.Workspace)
307
+ StatusService.log('Setup marked as complete')
308
+
309
+ // Test connection
310
+ const testConnection = await vscode.window.showInformationMessage(
311
+ '✅ Configuration saved!\n\nWould you like to test the connection to verify everything works?',
312
+ { modal: true },
313
+ 'Test Now',
314
+ 'Skip'
315
+ )
316
+
317
+ if (testConnection === 'Test Now') {
318
+ StatusService.log('User requested connection test')
319
+ await vscode.commands.executeCommand('ai-changelog.testConnection')
320
+ } else {
321
+ vscode.window.showInformationMessage(
322
+ '🎉 Setup complete! You can test the connection anytime with "AI Changelog: Test Connection"'
323
+ )
324
+ }
325
+
326
+ return true
327
+ } catch (error) {
328
+ const errorMsg = error instanceof Error ? error.message : String(error)
329
+ StatusService.log(`✗ Setup wizard failed: ${errorMsg}`)
330
+ vscode.window.showErrorMessage(`Setup failed: ${errorMsg}`)
331
+ return false
332
+ }
333
+ }
@@ -0,0 +1,93 @@
1
+ import * as vscode from 'vscode'
2
+ import { ExtensionConfigurationManager } from '../services/ExtensionConfigurationManager'
3
+ import { StatusService } from '../services/StatusService'
4
+
5
+ export async function testConnection(
6
+ configManager: ExtensionConfigurationManager
7
+ ): Promise<void> {
8
+ const provider = configManager.getCurrentProvider()
9
+
10
+ StatusService.log(`Testing connection to ${provider}...`, true)
11
+
12
+ await vscode.window.withProgress(
13
+ {
14
+ location: vscode.ProgressLocation.Notification,
15
+ title: `Testing ${provider} connection...`,
16
+ cancellable: false,
17
+ },
18
+ async (progress) => {
19
+ try {
20
+ progress.report({ increment: 30, message: 'Checking configuration...' })
21
+
22
+ // Ensure config manager is initialized to load env vars if needed
23
+ if (!configManager.isInitialized()) {
24
+ await configManager.initialize()
25
+ }
26
+
27
+ // Check if API key exists (for cloud providers)
28
+ if (provider !== 'ollama' && provider !== 'lmstudio') {
29
+ // Check in config manager (which includes env vars)
30
+ const keyName = configManager['getKeyNameForProvider'](provider)
31
+ const apiKey = configManager.get(keyName)
32
+
33
+ if (!apiKey || apiKey.trim().length === 0) {
34
+ throw new Error(`No API key configured for ${provider}. Storage mode: ${configManager.getStorageMode()}`)
35
+ }
36
+ StatusService.log(`✓ API key found for ${provider}`)
37
+ }
38
+
39
+ progress.report({ increment: 30, message: 'Initializing...' })
40
+
41
+ // Try to import and initialize the ApplicationService
42
+ const { ApplicationService } = await import(
43
+ '@entro314labs/ai-changelog-generator/src/application/services/application.service.js'
44
+ )
45
+
46
+ const workspaceFolders = vscode.workspace.workspaceFolders
47
+ if (!workspaceFolders) {
48
+ throw new Error('No workspace folder open')
49
+ }
50
+
51
+ const appService = new ApplicationService({
52
+ configManager: configManager,
53
+ cwd: workspaceFolders[0].uri.fsPath,
54
+ })
55
+
56
+ progress.report({ increment: 40, message: 'Testing AI provider...' })
57
+
58
+ // This will test if the provider can be initialized
59
+ // For a real test, we'd need to make a small API call
60
+ StatusService.log(`✓ ${provider} provider initialized successfully`)
61
+
62
+ vscode.window.showInformationMessage(
63
+ `✅ Connection to ${provider} successful!\n\nProvider is configured and ready to use.`,
64
+ 'View Details'
65
+ ).then((action) => {
66
+ if (action === 'View Details') {
67
+ vscode.commands.executeCommand('ai-changelog.showStatus')
68
+ }
69
+ })
70
+
71
+ StatusService.log(`Connection test passed for ${provider}`)
72
+ } catch (error) {
73
+ const errorMessage = error instanceof Error ? error.message : String(error)
74
+ StatusService.log(`✗ Connection test failed: ${errorMessage}`)
75
+
76
+ const action = await vscode.window.showErrorMessage(
77
+ `❌ Connection to ${provider} failed:\n\n${errorMessage}`,
78
+ 'View Logs',
79
+ 'Reconfigure',
80
+ 'Check Status'
81
+ )
82
+
83
+ if (action === 'View Logs') {
84
+ vscode.commands.executeCommand('ai-changelog.showLogs')
85
+ } else if (action === 'Reconfigure') {
86
+ vscode.commands.executeCommand('ai-changelog.setup')
87
+ } else if (action === 'Check Status') {
88
+ vscode.commands.executeCommand('ai-changelog.showStatus')
89
+ }
90
+ }
91
+ }
92
+ )
93
+ }
@@ -0,0 +1,264 @@
1
+ import * as vscode from 'vscode'
2
+ import { CommitSidebarProvider } from './views/CommitSidebarProvider'
3
+ import { ReleaseSidebarProvider } from './views/ReleaseSidebarProvider'
4
+ import { SettingsPanelProvider } from './views/SettingsPanelProvider'
5
+ import { OnboardingPanelProvider } from './views/OnboardingPanelProvider'
6
+ import { ExtensionConfigurationManager } from './services/ExtensionConfigurationManager'
7
+ import { EnvFileService } from './services/EnvFileService'
8
+ import { StatusService } from './services/StatusService'
9
+ import { configureProviderCommand } from './commands/configureProvider'
10
+ import { setupWizard } from './commands/setupWizard'
11
+ import { testConnection } from './commands/testConnection'
12
+
13
+ export async function activate(context: vscode.ExtensionContext) {
14
+ console.log('AI Changelog Generator extension is activating...')
15
+
16
+ try {
17
+ // Initialize StatusService first
18
+ StatusService.initialize(context)
19
+ StatusService.log('Extension activation started')
20
+
21
+ // Initialize configuration manager
22
+ const configManager = new ExtensionConfigurationManager(context.secrets)
23
+
24
+ // Check if setup is complete
25
+ const setupComplete = configManager.isSetupComplete()
26
+ StatusService.log(`Setup complete: ${setupComplete}`)
27
+
28
+ if (!setupComplete) {
29
+ // Update status bar
30
+ StatusService.updateStatus(configManager)
31
+
32
+ // Show onboarding panel
33
+ StatusService.log('Opening onboarding panel...')
34
+ OnboardingPanelProvider.createOrShow(context.extensionUri, configManager)
35
+ } else {
36
+ // Load configuration
37
+ await configManager.initialize()
38
+ StatusService.log('Configuration loaded successfully')
39
+
40
+ // Update status bar
41
+ StatusService.updateStatus(configManager)
42
+
43
+ // Auto-detect environment variables if enabled
44
+ const wsConfig = vscode.workspace.getConfiguration('aiChangelog')
45
+ const autoDetect = wsConfig.get<boolean>('autoDetectEnv', true)
46
+ const storageMode = configManager.getStorageMode()
47
+
48
+ if (autoDetect && storageMode !== 'env') {
49
+ const hasEnvVars = await EnvFileService.hasEnvVars()
50
+ if (hasEnvVars) {
51
+ StatusService.log('Env vars detected, asking user...')
52
+ const useEnv = await vscode.window.showInformationMessage(
53
+ '🔍 Detected API keys in .env files. Would you like to use them?',
54
+ 'Use .env',
55
+ 'Keep Current',
56
+ "Don't Ask Again"
57
+ )
58
+
59
+ if (useEnv === 'Use .env') {
60
+ StatusService.log('Switching to .env storage mode')
61
+ await wsConfig.update('storageMode', 'env', vscode.ConfigurationTarget.Workspace)
62
+ await configManager.initialize() // Reload with env vars
63
+ StatusService.updateStatus(configManager)
64
+ vscode.window.showInformationMessage('✅ Now using API keys from .env file')
65
+ } else if (useEnv === "Don't Ask Again") {
66
+ StatusService.log('User disabled auto-detect')
67
+ await wsConfig.update('autoDetectEnv', false, vscode.ConfigurationTarget.Workspace)
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ console.log('Configuration manager initialized')
74
+ StatusService.log('Registering commands...')
75
+
76
+ // Register Settings Panel Provider
77
+ const settingsProvider = new SettingsPanelProvider(context.extensionUri, configManager)
78
+ context.subscriptions.push(
79
+ vscode.window.registerWebviewViewProvider(
80
+ SettingsPanelProvider.viewType,
81
+ settingsProvider
82
+ )
83
+ )
84
+ StatusService.log('Settings panel provider registered')
85
+
86
+ // Register all commands
87
+ context.subscriptions.push(
88
+ vscode.commands.registerCommand('ai-changelog.setup', async () => {
89
+ StatusService.log('Setup command invoked - opening onboarding panel')
90
+ OnboardingPanelProvider.createOrShow(context.extensionUri, configManager)
91
+ })
92
+ )
93
+
94
+ context.subscriptions.push(
95
+ vscode.commands.registerCommand('ai-changelog.testConnection', async () => {
96
+ StatusService.log('Test connection command invoked')
97
+ await testConnection(configManager)
98
+ })
99
+ )
100
+
101
+ context.subscriptions.push(
102
+ vscode.commands.registerCommand('ai-changelog.showStatus', async () => {
103
+ StatusService.log('Show status command invoked')
104
+ await StatusService.showStatusReport(configManager)
105
+ })
106
+ )
107
+
108
+ context.subscriptions.push(
109
+ vscode.commands.registerCommand('ai-changelog.showLogs', () => {
110
+ StatusService.log('Show logs command invoked')
111
+ StatusService.showOutputChannel()
112
+ })
113
+ )
114
+
115
+ context.subscriptions.push(
116
+ vscode.commands.registerCommand('ai-changelog.detectEnv', async () => {
117
+ StatusService.log('Detect env command invoked')
118
+ const envVars = await EnvFileService.detectEnvironmentVariables()
119
+ if (Object.keys(envVars).length === 0) {
120
+ vscode.window.showInformationMessage('No API keys found in .env files')
121
+ StatusService.log('No env vars found')
122
+ } else {
123
+ const keys = Object.keys(envVars).join(', ')
124
+ vscode.window.showInformationMessage(`Found keys: ${keys}`)
125
+ StatusService.log(`Found env vars: ${keys}`)
126
+ }
127
+ })
128
+ )
129
+
130
+ context.subscriptions.push(
131
+ vscode.commands.registerCommand('ai-changelog.configure', () => {
132
+ StatusService.log('Configure provider command invoked')
133
+ configureProviderCommand(configManager)
134
+ })
135
+ )
136
+
137
+ // Listen for configuration changes and provide immediate feedback
138
+ context.subscriptions.push(
139
+ vscode.workspace.onDidChangeConfiguration(async (e) => {
140
+ if (e.affectsConfiguration('aiChangelog')) {
141
+ StatusService.log('Configuration changed, validating...')
142
+
143
+ // Reinitialize config manager
144
+ await configManager.initialize()
145
+
146
+ // Update status bar
147
+ StatusService.updateStatus(configManager)
148
+
149
+ // Validate provider changes
150
+ if (e.affectsConfiguration('aiChangelog.provider')) {
151
+ const provider = vscode.workspace.getConfiguration('aiChangelog').get<string>('provider')
152
+ StatusService.log(`Provider changed to: ${provider}`)
153
+
154
+ const hasKey = await configManager.hasApiKey(provider || 'openai')
155
+ if (!hasKey && provider !== 'ollama' && provider !== 'lmstudio') {
156
+ vscode.window.showWarningMessage(
157
+ `⚠️ Provider changed to ${provider} but no API key is configured.`,
158
+ 'Open Settings'
159
+ ).then((action) => {
160
+ if (action === 'Open Settings') {
161
+ vscode.commands.executeCommand('ai-changelog-settings-view.focus')
162
+ }
163
+ })
164
+ } else {
165
+ vscode.window.showInformationMessage(`✅ Provider set to ${provider}`)
166
+ }
167
+ }
168
+
169
+ // Validate storage mode changes
170
+ if (e.affectsConfiguration('aiChangelog.storageMode')) {
171
+ const mode = vscode.workspace.getConfiguration('aiChangelog').get<string>('storageMode')
172
+ StatusService.log(`Storage mode changed to: ${mode}`)
173
+
174
+ if (mode === 'env') {
175
+ const envVars = await EnvFileService.detectEnvironmentVariables()
176
+ if (Object.keys(envVars).length === 0) {
177
+ vscode.window.showWarningMessage(
178
+ '⚠️ Storage mode set to .env but no .env file found. Create .env.local in workspace root.'
179
+ )
180
+ } else {
181
+ vscode.window.showInformationMessage(
182
+ `✅ Found ${Object.keys(envVars).length} API key(s) in .env file`
183
+ )
184
+ }
185
+ } else {
186
+ vscode.window.showInformationMessage(`✅ Storage mode set to ${mode}`)
187
+ }
188
+ }
189
+
190
+ StatusService.log('Configuration validation complete')
191
+ }
192
+ })
193
+ )
194
+
195
+ // Register the Commit Sidebar Provider
196
+ const sidebarProvider = new CommitSidebarProvider(context.extensionUri, configManager)
197
+ context.subscriptions.push(
198
+ vscode.window.registerWebviewViewProvider('ai-changelog-commit-view', sidebarProvider)
199
+ )
200
+ StatusService.log('Commit sidebar provider registered')
201
+
202
+ // Register Release Provider
203
+ const releaseProvider = new ReleaseSidebarProvider(context.extensionUri, configManager)
204
+ context.subscriptions.push(
205
+ vscode.window.registerWebviewViewProvider('ai-changelog-release-view', releaseProvider)
206
+ )
207
+ StatusService.log('Release sidebar provider registered')
208
+
209
+ // Register Commands
210
+ context.subscriptions.push(
211
+ vscode.commands.registerCommand('ai-changelog.generateCommit', async () => {
212
+ StatusService.log('Generate commit command invoked')
213
+ if (!configManager.isSetupComplete()) {
214
+ StatusService.log('Setup not complete, prompting user')
215
+ const runSetup = await vscode.window.showWarningMessage(
216
+ 'AI Changelog Generator is not set up yet. Would you like to run the setup wizard?',
217
+ 'Setup Now',
218
+ 'Cancel'
219
+ )
220
+ if (runSetup === 'Setup Now') {
221
+ await vscode.commands.executeCommand('ai-changelog.setup')
222
+ }
223
+ return
224
+ }
225
+ await vscode.commands.executeCommand('ai-changelog-commit-view.focus')
226
+ })
227
+ )
228
+
229
+ context.subscriptions.push(
230
+ vscode.commands.registerCommand('ai-changelog.generateRelease', async () => {
231
+ StatusService.log('Generate release command invoked')
232
+ if (!configManager.isSetupComplete()) {
233
+ StatusService.log('Setup not complete, prompting user')
234
+ const runSetup = await vscode.window.showWarningMessage(
235
+ 'AI Changelog Generator is not set up yet. Would you like to run the setup wizard?',
236
+ 'Setup Now',
237
+ 'Cancel'
238
+ )
239
+ if (runSetup === 'Setup Now') {
240
+ await vscode.commands.executeCommand('ai-changelog.setup')
241
+ }
242
+ return
243
+ }
244
+ await vscode.commands.executeCommand('ai-changelog-release-view.focus')
245
+ })
246
+ )
247
+
248
+ console.log('AI Changelog Generator extension is now active!')
249
+ StatusService.log('Extension activated successfully')
250
+ } catch (error) {
251
+ const errorMessage = error instanceof Error ? error.message : String(error)
252
+ console.error('Failed to activate AI Changelog Generator extension:', errorMessage)
253
+ StatusService.log(`✗ Extension activation failed: ${errorMessage}`)
254
+ vscode.window.showErrorMessage(
255
+ `AI Changelog Generator failed to activate: ${errorMessage}`
256
+ )
257
+ }
258
+ }
259
+
260
+ export function deactivate() {
261
+ console.log('AI Changelog Generator extension is deactivating...')
262
+ StatusService.log('Extension deactivating')
263
+ StatusService.dispose()
264
+ }