|
|
|
class APIPanel { |
|
constructor() { |
|
|
|
this.init(); |
|
} |
|
|
|
async init() { |
|
this.providerSelect = document.getElementById('api-provider'); |
|
this.modelSelect = document.getElementById('api-model'); |
|
this.keysContainer = document.querySelector('.api-keys-container'); |
|
|
|
|
|
await this.fetchAPIConfigs(); |
|
|
|
this.providerSelect.addEventListener('change', () => this.updateProviderUI()); |
|
this.initAPIForm(); |
|
this.updateProviderUI(); |
|
} |
|
|
|
async fetchAPIConfigs() { |
|
try { |
|
|
|
if (window.ws && window.ws.readyState === WebSocket.OPEN) { |
|
window.ws.send(JSON.stringify({ |
|
type: 'request_api_configs' |
|
})); |
|
} |
|
|
|
|
|
await new Promise((resolve) => { |
|
const configHandler = (event) => { |
|
const message = JSON.parse(event.data); |
|
if (message.type === 'api_configs') { |
|
this.modelConfigs = message.data; |
|
window.removeEventListener('message', configHandler); |
|
resolve(); |
|
} |
|
}; |
|
window.ws.addEventListener('message', configHandler); |
|
}); |
|
|
|
|
|
this.initProviderSelect(); |
|
} catch (error) { |
|
console.error('获取API配置失败:', error); |
|
|
|
this.modelConfigs = this.getDefaultConfigs(); |
|
this.initProviderSelect(); |
|
} |
|
} |
|
|
|
getDefaultConfigs() { |
|
|
|
return { |
|
openai: { |
|
label: 'OpenAI API Key', |
|
models: ['gpt-3.5-turbo', 'gpt-4'], |
|
envKey: 'OPENAI_API_KEY' |
|
}, |
|
anthropic: { |
|
label: 'Claude API Key', |
|
models: ['claude-3-opus', 'claude-3-sonnet'], |
|
envKey: 'ANTHROPIC_API_KEY' |
|
} |
|
}; |
|
} |
|
|
|
initProviderSelect() { |
|
this.providerSelect.innerHTML = Object.entries(this.modelConfigs) |
|
.map(([key, config]) => ` |
|
<option value="${key}">${config.label.split(' API Key')[0]}</option> |
|
`) |
|
.join(''); |
|
} |
|
|
|
updateProviderUI() { |
|
const provider = this.providerSelect.value; |
|
|
|
|
|
this.keysContainer.innerHTML = this.createKeyInput( |
|
this.modelConfigs[provider].label, |
|
this.modelConfigs[provider].envKey |
|
); |
|
|
|
|
|
this.modelSelect.innerHTML = this.modelConfigs[provider].models |
|
.map(model => `<option value="${model}">${model}</option>`) |
|
.join(''); |
|
|
|
|
|
const toggles = document.querySelectorAll('.toggle-visibility'); |
|
toggles.forEach(toggle => { |
|
toggle.addEventListener('click', (e) => { |
|
const input = e.target.previousElementSibling; |
|
const type = input.type === 'password' ? 'text' : 'password'; |
|
input.type = type; |
|
e.target.innerHTML = type === 'password' ? '👁️' : '👁️🗨️'; |
|
}); |
|
}); |
|
} |
|
|
|
createKeyInput(label, envKey) { |
|
return ` |
|
<div class="api-key-input"> |
|
<label>${label}</label> |
|
<div style="position: relative;"> |
|
<input type="password" |
|
data-env-key="${envKey}" |
|
placeholder="Enter API Key"> |
|
<span class="toggle-visibility">👁️</span> |
|
</div> |
|
</div> |
|
`; |
|
} |
|
|
|
initAPIForm() { |
|
const submitBtn = document.querySelector('.api-submit-btn'); |
|
if (submitBtn) { |
|
submitBtn.addEventListener('click', () => { |
|
const provider = this.providerSelect.value; |
|
const model = this.modelSelect.value; |
|
const apiKey = document.querySelector(`[data-env-key="${this.modelConfigs[provider].envKey}"]`).value; |
|
|
|
if (window.ws && window.ws.readyState === WebSocket.OPEN) { |
|
window.ws.send(JSON.stringify({ |
|
type: 'api_settings', |
|
data: { |
|
provider: provider, |
|
model: model, |
|
apiKey: apiKey, |
|
envKey: this.modelConfigs[provider].envKey |
|
} |
|
})); |
|
} |
|
}); |
|
} |
|
} |
|
} |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
new APIPanel(); |
|
}); |
|
|