fix: handle undefined safeStorage and remove diagnostic logging

Root cause: electron.safeStorage was undefined (not null) when the
property doesn't exist, causing "Cannot read properties of undefined"
error when accessing isEncryptionAvailable.

Fix: Normalize undefined to null with `|| null` operator when importing
safeStorage, ensuring consistent null checks throughout the code.

Changes:
- Set safeStorage to null if electron.safeStorage is undefined
- Remove all diagnostic try-catch blocks from settings UI
- Remove console.log debugging statements
- Restore clean code that now works correctly

This resolves the settings UI crash that prevented the API key
management section from displaying.
This commit is contained in:
2025-10-26 00:16:35 -04:00
parent efd1ff306e
commit 779b3d6e8c
2 changed files with 57 additions and 81 deletions

View File

@@ -61,94 +61,70 @@ export class MCPServerSettingTab extends PluginSettingTab {
// Authentication (Always Enabled)
containerEl.createEl('h3', {text: 'Authentication'});
try {
const authDesc = containerEl.createEl('p', {
text: 'Authentication is required for all requests. Your API key is encrypted and stored securely using your system\'s credential storage.'
});
authDesc.style.fontSize = '0.9em';
authDesc.style.color = 'var(--text-muted)';
authDesc.style.marginBottom = '16px';
const authDesc = containerEl.createEl('p', {
text: 'Authentication is required for all requests. Your API key is encrypted and stored securely using your system\'s credential storage.'
});
authDesc.style.fontSize = '0.9em';
authDesc.style.color = 'var(--text-muted)';
authDesc.style.marginBottom = '16px';
// Show encryption status
const encryptionAvailable = isEncryptionAvailable();
console.log('[Settings] Encryption available:', encryptionAvailable);
const encryptionStatus = containerEl.createEl('p', {
text: encryptionAvailable
? '🔒 Encryption: Available (using system keychain)'
: '⚠️ Encryption: Unavailable (API key stored in plaintext)'
});
encryptionStatus.style.fontSize = '0.85em';
encryptionStatus.style.marginBottom = '12px';
encryptionStatus.style.fontStyle = 'italic';
} catch (error) {
console.error('[Settings] Error in auth description section:', error);
containerEl.createEl('p', {
text: '⚠️ Error displaying authentication section: ' + (error instanceof Error ? error.message : String(error)),
cls: 'mod-error'
});
}
// Show encryption status
const encryptionStatus = containerEl.createEl('p', {
text: isEncryptionAvailable()
? '🔒 Encryption: Available (using system keychain)'
: '⚠️ Encryption: Unavailable (API key stored in plaintext)'
});
encryptionStatus.style.fontSize = '0.85em';
encryptionStatus.style.marginBottom = '12px';
encryptionStatus.style.fontStyle = 'italic';
// API Key Display (always show - auth is always enabled)
console.log('[Settings] About to render API key section');
console.log('[Settings] API key length:', (this.plugin.settings.apiKey || '').length);
new Setting(containerEl)
.setName('API Key Management')
.setDesc('Use this key in the Authorization header as Bearer token');
try {
new Setting(containerEl)
.setName('API Key Management')
.setDesc('Use this key in the Authorization header as Bearer token');
// Create a full-width container for buttons and key display
const apiKeyContainer = containerEl.createDiv({cls: 'mcp-api-key-section'});
apiKeyContainer.style.marginBottom = '20px';
apiKeyContainer.style.marginLeft = '0';
// Create a full-width container for buttons and key display
const apiKeyContainer = containerEl.createDiv({cls: 'mcp-api-key-section'});
apiKeyContainer.style.marginBottom = '20px';
apiKeyContainer.style.marginLeft = '0';
// Create button container
const apiKeyButtonContainer = apiKeyContainer.createDiv({cls: 'mcp-api-key-buttons'});
apiKeyButtonContainer.style.display = 'flex';
apiKeyButtonContainer.style.gap = '8px';
apiKeyButtonContainer.style.marginBottom = '12px';
// Create button container
const apiKeyButtonContainer = apiKeyContainer.createDiv({cls: 'mcp-api-key-buttons'});
apiKeyButtonContainer.style.display = 'flex';
apiKeyButtonContainer.style.gap = '8px';
apiKeyButtonContainer.style.marginBottom = '12px';
// Copy button
const copyButton = apiKeyButtonContainer.createEl('button', {text: '📋 Copy Key'});
copyButton.addEventListener('click', async () => {
await navigator.clipboard.writeText(this.plugin.settings.apiKey || '');
new Notice('✅ API key copied to clipboard');
});
// Copy button
const copyButton = apiKeyButtonContainer.createEl('button', {text: '📋 Copy Key'});
copyButton.addEventListener('click', async () => {
await navigator.clipboard.writeText(this.plugin.settings.apiKey || '');
new Notice('✅ API key copied to clipboard');
});
// Regenerate button
const regenButton = apiKeyButtonContainer.createEl('button', {text: '🔄 Regenerate Key'});
regenButton.addEventListener('click', async () => {
this.plugin.settings.apiKey = generateApiKey();
await this.plugin.saveSettings();
new Notice('✅ New API key generated');
if (this.plugin.mcpServer?.isRunning()) {
new Notice('⚠️ Server restart required for API key changes to take effect');
}
this.display();
});
// Regenerate button
const regenButton = apiKeyButtonContainer.createEl('button', {text: '🔄 Regenerate Key'});
regenButton.addEventListener('click', async () => {
this.plugin.settings.apiKey = generateApiKey();
await this.plugin.saveSettings();
new Notice('✅ New API key generated');
if (this.plugin.mcpServer?.isRunning()) {
new Notice('⚠️ Server restart required for API key changes to take effect');
}
this.display();
});
// API Key display (static, copyable text)
const keyDisplayContainer = apiKeyContainer.createDiv({cls: 'mcp-api-key-display'});
keyDisplayContainer.style.padding = '12px';
keyDisplayContainer.style.backgroundColor = 'var(--background-secondary)';
keyDisplayContainer.style.borderRadius = '4px';
keyDisplayContainer.style.fontFamily = 'monospace';
keyDisplayContainer.style.fontSize = '0.9em';
keyDisplayContainer.style.wordBreak = 'break-all';
keyDisplayContainer.style.userSelect = 'all';
keyDisplayContainer.style.cursor = 'text';
keyDisplayContainer.style.marginBottom = '16px';
keyDisplayContainer.textContent = this.plugin.settings.apiKey || '';
console.log('[Settings] API key section rendered successfully');
} catch (error) {
console.error('[Settings] Error rendering API key section:', error);
containerEl.createEl('p', {
text: '⚠️ Error displaying API key: ' + (error instanceof Error ? error.message : String(error)),
cls: 'mod-error'
});
}
// API Key display (static, copyable text)
const keyDisplayContainer = apiKeyContainer.createDiv({cls: 'mcp-api-key-display'});
keyDisplayContainer.style.padding = '12px';
keyDisplayContainer.style.backgroundColor = 'var(--background-secondary)';
keyDisplayContainer.style.borderRadius = '4px';
keyDisplayContainer.style.fontFamily = 'monospace';
keyDisplayContainer.style.fontSize = '0.9em';
keyDisplayContainer.style.wordBreak = 'break-all';
keyDisplayContainer.style.userSelect = 'all';
keyDisplayContainer.style.cursor = 'text';
keyDisplayContainer.style.marginBottom = '16px';
keyDisplayContainer.textContent = this.plugin.settings.apiKey || '';
// MCP Client Configuration (show always, regardless of auth)
containerEl.createEl('h3', {text: 'MCP Client Configuration'});

View File

@@ -2,7 +2,7 @@
let safeStorage: any = null;
try {
const electron = require('electron');
safeStorage = electron.safeStorage;
safeStorage = electron.safeStorage || null;
} catch (error) {
console.warn('Electron safeStorage not available, API keys will be stored in plaintext');
}