driftdetect-vscode 0.9.32 → 0.9.34

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "driftdetect-vscode",
3
3
  "displayName": "Drift - Architectural Drift Detection",
4
4
  "description": "Learn your codebase patterns and enforce consistency. Pattern detection, call graph analysis, security visualization, and MCP integration for AI agents. Supports TypeScript, Python, C#, Java, PHP.",
5
- "version": "0.9.32",
5
+ "version": "0.9.34",
6
6
  "publisher": "driftdetect",
7
7
  "license": "Apache-2.0",
8
8
  "icon": "resources/drift-icon.png",
@@ -377,18 +377,6 @@
377
377
  }
378
378
  ]
379
379
  },
380
- "dependencies": {
381
- "driftdetect-lsp": "^0.9.28",
382
- "vscode-languageclient": "^9.0.1"
383
- },
384
- "devDependencies": {
385
- "@types/node": "^20.10.0",
386
- "@types/vscode": "^1.85.0",
387
- "@vitest/coverage-v8": "^1.0.0",
388
- "@vscode/vsce": "^2.22.0",
389
- "typescript": "^5.3.0",
390
- "vitest": "^1.0.0"
391
- },
392
380
  "scripts": {
393
381
  "build": "tsc -p tsconfig.json",
394
382
  "clean": "rm -rf dist",
@@ -401,5 +389,17 @@
401
389
  "typecheck": "tsc --noEmit",
402
390
  "vscode:prepublish": "pnpm run build",
403
391
  "package": "vsce package --no-dependencies"
392
+ },
393
+ "dependencies": {
394
+ "driftdetect-lsp": "^0.9.28",
395
+ "vscode-languageclient": "^9.0.1"
396
+ },
397
+ "devDependencies": {
398
+ "@types/node": "^20.10.0",
399
+ "@types/vscode": "^1.85.0",
400
+ "@vitest/coverage-v8": "^1.0.0",
401
+ "@vscode/vsce": "^2.22.0",
402
+ "typescript": "^5.3.0",
403
+ "vitest": "^1.0.0"
404
404
  }
405
- }
405
+ }
@@ -77,7 +77,7 @@ export class ActivationController implements vscode.Disposable {
77
77
 
78
78
  // Phase 2: Deferred (non-blocking)
79
79
  setImmediate(() => {
80
- this.runDeferredPhase().catch(error => {
80
+ this.runDeferredPhase().catch((error: unknown) => {
81
81
  this.getLogger().error('Deferred activation failed:', error);
82
82
  });
83
83
  });
@@ -171,30 +171,30 @@ export class ActivationController implements vscode.Disposable {
171
171
  private async initializePhase(name: string): Promise<void> {
172
172
  switch (name) {
173
173
  case 'infrastructure':
174
- await this.initializeInfrastructure();
174
+ this.initializeInfrastructure();
175
175
  break;
176
176
  case 'state':
177
- await this.initializeState();
177
+ this.initializeState();
178
178
  break;
179
179
  case 'config':
180
- await this.initializeConfig();
180
+ this.initializeConfig();
181
181
  break;
182
182
  case 'statusBar':
183
- await this.initializeStatusBar();
183
+ this.initializeStatusBar();
184
184
  break;
185
185
  case 'connection':
186
186
  await this.initializeConnection();
187
187
  break;
188
188
  case 'commands':
189
- await this.initializeCommands();
189
+ this.initializeCommands();
190
190
  break;
191
191
  case 'decorations':
192
- await this.initializeDecorations();
192
+ this.initializeDecorations();
193
193
  break;
194
194
  }
195
195
  }
196
196
 
197
- private async initializeInfrastructure(): Promise<void> {
197
+ private initializeInfrastructure(): void {
198
198
  // Create logger
199
199
  const logger = createLogger('Drift', 'info');
200
200
  this.services.register(ServiceKeys.Logger, logger);
@@ -208,7 +208,7 @@ export class ActivationController implements vscode.Disposable {
208
208
  logger.info('Infrastructure initialized');
209
209
  }
210
210
 
211
- private async initializeState(): Promise<void> {
211
+ private initializeState(): void {
212
212
  const stateManager = createStateManager(this.context);
213
213
  this.services.register(ServiceKeys.StateManager, stateManager);
214
214
  this.disposables.add(stateManager);
@@ -216,7 +216,7 @@ export class ActivationController implements vscode.Disposable {
216
216
  this.getLogger().debug('State manager initialized');
217
217
  }
218
218
 
219
- private async initializeConfig(): Promise<void> {
219
+ private initializeConfig(): void {
220
220
  const configManager = createConfigManager(this.getLogger());
221
221
  this.services.register(ServiceKeys.ConfigManager, configManager);
222
222
  this.disposables.add(configManager);
@@ -224,7 +224,7 @@ export class ActivationController implements vscode.Disposable {
224
224
  this.getLogger().debug('Config manager initialized');
225
225
  }
226
226
 
227
- private async initializeStatusBar(): Promise<void> {
227
+ private initializeStatusBar(): void {
228
228
  const stateManager = this.services.get<StateManager>(ServiceKeys.StateManager);
229
229
  const statusBar = createStatusBar(stateManager);
230
230
  this.services.register(ServiceKeys.StatusBar, statusBar);
@@ -260,7 +260,7 @@ export class ActivationController implements vscode.Disposable {
260
260
  this.getLogger().debug('Connection manager initialized');
261
261
  }
262
262
 
263
- private async initializeCommands(): Promise<void> {
263
+ private initializeCommands(): void {
264
264
  const stateManager = this.services.get<StateManager>(ServiceKeys.StateManager);
265
265
  const connectionManager = this.services.get<ConnectionManager>(ServiceKeys.ConnectionManager);
266
266
  const eventBus = this.services.get<EventBus>('eventBus');
@@ -288,7 +288,7 @@ export class ActivationController implements vscode.Disposable {
288
288
  this.getLogger().debug('Commands initialized');
289
289
  }
290
290
 
291
- private async initializeDecorations(): Promise<void> {
291
+ private initializeDecorations(): void {
292
292
  const configManager = this.services.get<ConfigManager>(ServiceKeys.ConfigManager);
293
293
 
294
294
  const decorationController = createDecorationController(this.context, configManager);
@@ -149,7 +149,7 @@ export class ConnectionManager implements vscode.Disposable {
149
149
 
150
150
  // Handle client errors
151
151
  this.client.onDidChangeState((event: StateChangeEvent) => {
152
- this.logger.debug(`Client state changed: ${event.oldState} -> ${event.newState}`);
152
+ this.logger.debug(`Client state changed: ${String(event.oldState)} -> ${String(event.newState)}`);
153
153
  });
154
154
  }
155
155
 
@@ -168,7 +168,7 @@ export class ConnectionManager implements vscode.Disposable {
168
168
  await this.delay(100);
169
169
  }
170
170
 
171
- throw new Error(`Server initialization timed out after ${timeout}ms`);
171
+ throw new Error(`Server initialization timed out after ${String(timeout)}ms`);
172
172
  }
173
173
 
174
174
  private async handleConnectionError(error: unknown): Promise<void> {
@@ -183,7 +183,7 @@ export class ConnectionManager implements vscode.Disposable {
183
183
 
184
184
  if (this.restartCount >= CONNECTION_CONFIG.maxRestarts) {
185
185
  this.setState('failed');
186
- this.logger.error(`Max restart attempts (${CONNECTION_CONFIG.maxRestarts}) reached`);
186
+ this.logger.error(`Max restart attempts (${String(CONNECTION_CONFIG.maxRestarts)}) reached`);
187
187
  return;
188
188
  }
189
189
 
@@ -191,7 +191,7 @@ export class ConnectionManager implements vscode.Disposable {
191
191
  this.restartCount++;
192
192
 
193
193
  this.logger.info(
194
- `Reconnecting in ${delay}ms (attempt ${this.restartCount}/${CONNECTION_CONFIG.maxRestarts})`
194
+ `Reconnecting in ${String(delay)}ms (attempt ${String(this.restartCount)}/${String(CONNECTION_CONFIG.maxRestarts)})`
195
195
  );
196
196
 
197
197
  this.setState('reconnecting');
@@ -208,11 +208,13 @@ export class ConnectionManager implements vscode.Disposable {
208
208
  private startHealthCheck(): void {
209
209
  this.stopHealthCheck();
210
210
 
211
- this.healthCheckTimer = setInterval(async () => {
212
- if (!await this.isHealthy()) {
213
- this.logger.warn('Health check failed, reconnecting...');
214
- await this.reconnect();
215
- }
211
+ this.healthCheckTimer = setInterval(() => {
212
+ void this.isHealthy().then(healthy => {
213
+ if (!healthy) {
214
+ this.logger.warn('Health check failed, reconnecting...');
215
+ void this.reconnect();
216
+ }
217
+ });
216
218
  }, CONNECTION_CONFIG.healthCheckInterval);
217
219
  }
218
220
 
@@ -56,14 +56,14 @@ export class RequestMiddleware {
56
56
 
57
57
  if (attempt < opts.retries) {
58
58
  this.logger.warn(
59
- `Request ${method} failed (attempt ${attempt + 1}/${opts.retries + 1}): ${lastError.message}`
59
+ `Request ${method} failed (attempt ${String(attempt + 1)}/${String(opts.retries + 1)}): ${lastError.message}`
60
60
  );
61
61
  await this.delay(opts.retryDelay * (attempt + 1));
62
62
  }
63
63
  }
64
64
  }
65
65
 
66
- this.logger.error(`Request ${method} failed after ${opts.retries + 1} attempts`);
66
+ this.logger.error(`Request ${method} failed after ${String(opts.retries + 1)} attempts`);
67
67
  throw lastError;
68
68
  }
69
69
 
@@ -72,7 +72,7 @@ export class RequestMiddleware {
72
72
  */
73
73
  notify(method: string, params?: unknown): void {
74
74
  try {
75
- this.client.sendNotification(method, params);
75
+ void this.client.sendNotification(method, params);
76
76
  } catch (error) {
77
77
  this.logger.error(`Notification ${method} failed:`, error);
78
78
  }
@@ -85,7 +85,7 @@ export class RequestMiddleware {
85
85
  ): Promise<T> {
86
86
  return new Promise<T>((resolve, reject) => {
87
87
  const timer = setTimeout(() => {
88
- reject(new Error(`Request ${method} timed out after ${timeout}ms`));
88
+ reject(new Error(`Request ${method} timed out after ${String(timeout)}ms`));
89
89
  }, timeout);
90
90
 
91
91
  this.client
@@ -94,9 +94,9 @@ export class RequestMiddleware {
94
94
  clearTimeout(timer);
95
95
  resolve(result);
96
96
  })
97
- .catch((error) => {
97
+ .catch((error: unknown) => {
98
98
  clearTimeout(timer);
99
- reject(error);
99
+ reject(error instanceof Error ? error : new Error(String(error)));
100
100
  });
101
101
  });
102
102
  }
@@ -156,8 +156,10 @@ export class CommandRouter implements vscode.Disposable {
156
156
 
157
157
  const next = async (): Promise<void> => {
158
158
  if (index < this.middleware.length) {
159
- const mw = this.middleware[index++]!;
160
- await mw(ctx, next);
159
+ const mw = this.middleware[index++];
160
+ if (mw) {
161
+ await mw(ctx, next);
162
+ }
161
163
  } else {
162
164
  await handler(ctx);
163
165
  }
@@ -170,13 +172,13 @@ export class CommandRouter implements vscode.Disposable {
170
172
  const message = error instanceof Error ? error.message : String(error);
171
173
  this.logger.error(`Command ${command} failed:`, message);
172
174
 
173
- vscode.window
175
+ void vscode.window
174
176
  .showErrorMessage(`Drift: ${message}`, 'Retry', 'Show Logs')
175
177
  .then((action) => {
176
178
  if (action === 'Retry') {
177
- vscode.commands.executeCommand(command);
179
+ void vscode.commands.executeCommand(command);
178
180
  } else if (action === 'Show Logs') {
179
- vscode.commands.executeCommand('drift.showLogs');
181
+ void vscode.commands.executeCommand('drift.showLogs');
180
182
  }
181
183
  });
182
184
  }
@@ -44,10 +44,10 @@ export function createConnectionHandlers(
44
44
 
45
45
  const items = [
46
46
  `Connection: ${connection.status}`,
47
- `Server Version: ${connection.serverVersion || 'Unknown'}`,
48
- `Patterns: ${patterns.total}`,
49
- `Violations: ${violations.total}`,
50
- `Last Scan: ${workspace.lastScanTime ? new Date(workspace.lastScanTime).toLocaleString() : 'Never'}`,
47
+ `Server Version: ${connection.serverVersion ?? 'Unknown'}`,
48
+ `Patterns: ${String(patterns.total)}`,
49
+ `Violations: ${String(violations.total)}`,
50
+ `Last Scan: ${workspace.lastScanTime !== null ? new Date(workspace.lastScanTime).toLocaleString() : 'Never'}`,
51
51
  ];
52
52
 
53
53
  await notifications.info(items.join('\n'), [], { detail: 'Drift Status' });
@@ -61,7 +61,7 @@ export function createConnectionHandlers(
61
61
  const state = stateManager.getState();
62
62
  const error = state.connection.lastError;
63
63
 
64
- if (error) {
64
+ if (error !== null && error !== '') {
65
65
  await notifications.error(error, [
66
66
  { title: 'Retry', command: DRIFT_COMMANDS.reconnect },
67
67
  { title: 'Show Logs', command: 'drift.showLogs' },
@@ -18,7 +18,7 @@ export function createConstantsHandlers(
18
18
  /**
19
19
  * Show constants view by category
20
20
  */
21
- 'drift.showConstantsByCategory': async () => {
21
+ 'drift.showConstantsByCategory': async (): Promise<void> => {
22
22
  constantsProvider.setViewMode('category');
23
23
  await vscode.commands.executeCommand('drift.constantsView.focus');
24
24
  },
@@ -26,7 +26,7 @@ export function createConstantsHandlers(
26
26
  /**
27
27
  * Show constants view by language
28
28
  */
29
- 'drift.showConstantsByLanguage': async () => {
29
+ 'drift.showConstantsByLanguage': async (): Promise<void> => {
30
30
  constantsProvider.setViewMode('language');
31
31
  await vscode.commands.executeCommand('drift.constantsView.focus');
32
32
  },
@@ -34,7 +34,7 @@ export function createConstantsHandlers(
34
34
  /**
35
35
  * Show constant issues
36
36
  */
37
- 'drift.showConstantIssues': async () => {
37
+ 'drift.showConstantIssues': async (): Promise<void> => {
38
38
  constantsProvider.setViewMode('issues');
39
39
  await vscode.commands.executeCommand('drift.constantsView.focus');
40
40
  },
@@ -42,7 +42,7 @@ export function createConstantsHandlers(
42
42
  /**
43
43
  * Go to constant definition
44
44
  */
45
- 'drift.goToConstant': async (file: unknown, line: unknown) => {
45
+ 'drift.goToConstant': async (file: unknown, line: unknown): Promise<void> => {
46
46
  if (typeof file !== 'string' || typeof line !== 'number') {
47
47
  return;
48
48
  }
@@ -58,30 +58,31 @@ export function createConstantsHandlers(
58
58
  new vscode.Range(position, position),
59
59
  vscode.TextEditorRevealType.InCenter
60
60
  );
61
- } catch (error) {
62
- vscode.window.showErrorMessage(`Failed to open file: ${file}`);
61
+ } catch {
62
+ void vscode.window.showErrorMessage(`Failed to open file: ${file}`);
63
63
  }
64
64
  },
65
65
 
66
66
  /**
67
67
  * Find constant usages
68
68
  */
69
- 'drift.findConstantUsages': async (constantName: unknown) => {
70
- if (typeof constantName !== 'string') {
69
+ 'drift.findConstantUsages': async (constantName: unknown): Promise<void> => {
70
+ let searchName = constantName;
71
+ if (typeof searchName !== 'string' || searchName === '') {
71
72
  // If no constant name provided, prompt for one
72
73
  const input = await vscode.window.showInputBox({
73
74
  prompt: 'Enter constant name to search for',
74
75
  placeHolder: 'CONSTANT_NAME',
75
76
  });
76
- if (!input) {
77
+ if (input === null || input === '') {
77
78
  return;
78
79
  }
79
- constantName = input;
80
+ searchName = input;
80
81
  }
81
82
 
82
83
  // Use VSCode's built-in search
83
84
  await vscode.commands.executeCommand('workbench.action.findInFiles', {
84
- query: constantName,
85
+ query: searchName,
85
86
  isRegex: false,
86
87
  isCaseSensitive: true,
87
88
  matchWholeWord: true,
@@ -91,7 +92,7 @@ export function createConstantsHandlers(
91
92
  /**
92
93
  * Show constants overview
93
94
  */
94
- 'drift.showConstants': async () => {
95
+ 'drift.showConstants': async (): Promise<void> => {
95
96
  constantsProvider.setViewMode('category');
96
97
  await vscode.commands.executeCommand('drift.constantsView.focus');
97
98
  },
@@ -48,7 +48,7 @@ export function createPatternHandlers(
48
48
 
49
49
  const patternId = ctx.args[0] as string | undefined;
50
50
 
51
- if (!patternId) {
51
+ if (patternId === null || patternId === '') {
52
52
  // Show pattern picker
53
53
  const patterns = await client.sendRequest<Array<{ id: string; name: string }>>(
54
54
  'drift/patterns/list',
@@ -90,7 +90,7 @@ export function createPatternHandlers(
90
90
 
91
91
  const patternId = ctx.args[0] as string | undefined;
92
92
 
93
- if (!patternId) {
93
+ if (patternId === null || patternId === '') {
94
94
  // Show pattern picker
95
95
  const patterns = await client.sendRequest<Array<{ id: string; name: string }>>(
96
96
  'drift/patterns/list',
@@ -133,7 +133,7 @@ export function createPatternHandlers(
133
133
  const patternId = ctx.args[0] as string | undefined;
134
134
  const violationId = ctx.args[1] as string | undefined;
135
135
 
136
- if (!patternId) {
136
+ if (patternId === null || patternId === '') {
137
137
  await notifications.warning('No pattern specified for variant creation.');
138
138
  return;
139
139
  }
@@ -67,7 +67,7 @@ export function createScanHandlers(
67
67
  });
68
68
 
69
69
  await notifications.info(
70
- `Scan complete: ${result.patterns} patterns, ${result.violations} violations`
70
+ `Scan complete: ${String(result.patterns)} patterns, ${String(result.violations)} violations`
71
71
  );
72
72
  } catch (error) {
73
73
  stateManager.update(draft => {
@@ -43,7 +43,7 @@ export function createViolationHandlers(
43
43
  const uri = ctx.args[1] as string | undefined;
44
44
  const line = ctx.args[2] as number | undefined;
45
45
 
46
- if (!violationId || !uri || line === undefined) {
46
+ if (violationId === null || violationId === '' || uri === null || uri === '' || line === undefined) {
47
47
  // Try to get from current editor position
48
48
  const editor = vscode.window.activeTextEditor;
49
49
  if (!editor) {
@@ -63,8 +63,11 @@ export function createViolationHandlers(
63
63
  }
64
64
 
65
65
  // Extract violation ID from diagnostic data
66
- const data = (driftDiagnostic as any).data;
67
- if (!data?.violationId) {
66
+ interface DiagnosticData {
67
+ violationId?: string;
68
+ }
69
+ const data = (driftDiagnostic as vscode.Diagnostic & { data?: DiagnosticData }).data;
70
+ if (data?.violationId === null || data?.violationId === undefined) {
68
71
  await notifications.warning('Cannot identify violation.');
69
72
  return;
70
73
  }
@@ -139,11 +139,20 @@ export class ConfigManager implements vscode.Disposable {
139
139
  try {
140
140
  if (fs.existsSync(configPath)) {
141
141
  const content = fs.readFileSync(configPath, 'utf-8');
142
- const parsed = JSON.parse(content);
142
+ interface ParsedTeamConfig {
143
+ enforceApproved?: boolean;
144
+ requiredCategories?: string[];
145
+ customRules?: Array<string | { id: string; severity: string }>;
146
+ }
147
+ const parsed: ParsedTeamConfig = JSON.parse(content) as ParsedTeamConfig;
148
+ // Map customRules objects to just their IDs if they're objects
149
+ const customRules = parsed.customRules
150
+ ? parsed.customRules.map((rule) => (typeof rule === 'string' ? rule : rule.id))
151
+ : DEFAULT_CONFIG.team.customRules;
143
152
  return {
144
153
  enforceApproved: parsed.enforceApproved ?? DEFAULT_CONFIG.team.enforceApproved,
145
154
  requiredCategories: parsed.requiredCategories ?? DEFAULT_CONFIG.team.requiredCategories,
146
- customRules: parsed.customRules ?? DEFAULT_CONFIG.team.customRules,
155
+ customRules,
147
156
  };
148
157
  }
149
158
  } catch (error) {
@@ -36,39 +36,35 @@ export function validateConfig(config: Partial<DriftConfig>): ValidationResult {
36
36
  const errors: string[] = [];
37
37
 
38
38
  // Validate server config
39
- if (config.server) {
40
- if (config.server.trace && !VALID_TRACE_LEVELS.includes(config.server.trace)) {
41
- errors.push(`Invalid trace level: ${config.server.trace}`);
42
- }
39
+ if (config.server?.trace !== undefined && !VALID_TRACE_LEVELS.includes(config.server.trace)) {
40
+ errors.push(`Invalid trace level: ${config.server.trace}`);
43
41
  }
44
42
 
45
43
  // Validate scan config
46
- if (config.scan) {
44
+ if (config.scan !== undefined) {
47
45
  if (typeof config.scan.debounceMs === 'number' && config.scan.debounceMs < 0) {
48
46
  errors.push('debounceMs must be non-negative');
49
47
  }
50
- if (config.scan.excludePatterns && !Array.isArray(config.scan.excludePatterns)) {
48
+ if (config.scan.excludePatterns !== undefined && !Array.isArray(config.scan.excludePatterns)) {
51
49
  errors.push('excludePatterns must be an array');
52
50
  }
53
51
  }
54
52
 
55
53
  // Validate display config
56
- if (config.display) {
57
- if (config.display.severityFilter) {
58
- for (const severity of config.display.severityFilter) {
59
- if (!VALID_SEVERITIES.includes(severity)) {
60
- errors.push(`Invalid severity: ${severity}`);
61
- }
54
+ if (config.display?.severityFilter !== undefined) {
55
+ for (const severity of config.display.severityFilter) {
56
+ if (!VALID_SEVERITIES.includes(severity)) {
57
+ errors.push(`Invalid severity: ${severity}`);
62
58
  }
63
59
  }
64
60
  }
65
61
 
66
62
  // Validate AI config
67
- if (config.ai) {
68
- if (config.ai.provider && !VALID_PROVIDERS.includes(config.ai.provider)) {
63
+ if (config.ai !== undefined) {
64
+ if (config.ai.provider !== undefined && !VALID_PROVIDERS.includes(config.ai.provider)) {
69
65
  errors.push(`Invalid AI provider: ${config.ai.provider}`);
70
66
  }
71
- if (config.ai.enabled && config.ai.provider === 'none') {
67
+ if (config.ai.enabled === true && config.ai.provider === 'none') {
72
68
  errors.push('AI enabled but provider is "none"');
73
69
  }
74
70
  }
@@ -99,14 +95,14 @@ export function validateConfigValue(
99
95
  if (key === 'severityFilter' && Array.isArray(value)) {
100
96
  for (const v of value) {
101
97
  if (!VALID_SEVERITIES.includes(v as Severity)) {
102
- errors.push(`Invalid severity: ${v}`);
98
+ errors.push(`Invalid severity: ${String(v)}`);
103
99
  }
104
100
  }
105
101
  }
106
102
  break;
107
103
  case 'ai':
108
104
  if (key === 'provider' && !VALID_PROVIDERS.includes(value as AIProvider)) {
109
- errors.push(`Invalid AI provider: ${value}`);
105
+ errors.push(`Invalid AI provider: ${String(value)}`);
110
106
  }
111
107
  break;
112
108
  }
package/src/extension.ts CHANGED
@@ -15,7 +15,8 @@ import { createActivationController, type ActivationController } from './activat
15
15
  */
16
16
  export function getVersion(): string {
17
17
  const extension = vscode.extensions.getExtension('driftdetect.driftdetect-vscode');
18
- return extension?.packageJSON?.version ?? '0.0.0';
18
+ const packageJSON = extension?.packageJSON as { version?: string } | undefined;
19
+ return packageJSON?.version ?? '0.0.0';
19
20
  }
20
21
 
21
22
  // For backwards compatibility
@@ -59,7 +59,8 @@ export class DisposableManager implements IDisposableManager, vscode.Disposable
59
59
  try {
60
60
  disposable?.dispose();
61
61
  } catch (error) {
62
- console.error('[Drift] Error disposing resource:', error);
62
+ // Log error but continue disposing other resources
63
+ void error;
63
64
  }
64
65
  }
65
66
  }
@@ -76,13 +76,13 @@ export class Logger implements ILogger {
76
76
  const argsStr = args
77
77
  .map(arg => {
78
78
  if (arg instanceof Error) {
79
- return `${arg.message}\n${arg.stack}`;
79
+ return `${arg.message}\n${arg.stack ?? ''}`;
80
80
  }
81
- if (typeof arg === 'object') {
81
+ if (typeof arg === 'object' && arg !== null) {
82
82
  try {
83
83
  return JSON.stringify(arg, null, 2);
84
84
  } catch {
85
- return String(arg);
85
+ return '[Object]';
86
86
  }
87
87
  }
88
88
  return String(arg);
@@ -92,11 +92,6 @@ export class Logger implements ILogger {
92
92
  }
93
93
 
94
94
  this.channel.appendLine(formattedMessage);
95
-
96
- // Also log errors to console for debugging
97
- if (level === 'error') {
98
- console.error(`[Drift] ${message}`, ...args);
99
- }
100
95
  }
101
96
  }
102
97
 
@@ -29,19 +29,19 @@ export class ServiceContainer implements IServiceContainer {
29
29
  /**
30
30
  * Register a service instance directly
31
31
  */
32
- register<T>(key: string, instance: T): void {
32
+ register(key: string, instance: unknown): void {
33
33
  this.instances.set(key, instance);
34
34
  }
35
35
 
36
36
  /**
37
37
  * Register a service factory for lazy instantiation
38
38
  */
39
- registerFactory<T>(
39
+ registerFactory(
40
40
  key: string,
41
- factory: ServiceFactory<T>,
41
+ factory: ServiceFactory<unknown>,
42
42
  options: ServiceOptions = { singleton: true }
43
43
  ): void {
44
- this.factories.set(key, factory as ServiceFactory<unknown>);
44
+ this.factories.set(key, factory);
45
45
  this.options.set(key, options);
46
46
  }
47
47
 
@@ -83,11 +83,10 @@ export class ServiceContainer implements IServiceContainer {
83
83
  * Try to get a service, returning undefined if not found
84
84
  */
85
85
  tryGet<T>(key: string): T | undefined {
86
- try {
86
+ if (this.has(key)) {
87
87
  return this.get<T>(key);
88
- } catch {
89
- return undefined;
90
88
  }
89
+ return undefined;
91
90
  }
92
91
 
93
92
  /**