diff --git a/desktop/src/pages/Settings.tsx b/desktop/src/pages/Settings.tsx index 8c692bea..48fa4abc 100644 --- a/desktop/src/pages/Settings.tsx +++ b/desktop/src/pages/Settings.tsx @@ -115,6 +115,27 @@ function ProviderSettings() { + {/* Official provider — always visible at top */} +
!isOfficialActive && handleActivateOfficial()} + > + +
+
+ Claude Official + {isOfficialActive && ( + ACTIVE + )} +
+
Anthropic native — no API key required
+
+
+ {/* Saved providers */} {isLoading && providers.length === 0 ? (
@@ -171,8 +192,10 @@ function ProviderSettings() {
)} - {/* Create Modal */} - setShowCreateModal(false)} mode="create" /> + {/* Create Modal — conditionally rendered so state resets on close */} + {showCreateModal && ( + setShowCreateModal(false)} mode="create" /> + )} {/* Edit Modal */} {editingProvider && ( @@ -195,7 +218,7 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) const { createProvider, updateProvider, testConfig } = useProviderStore() const fetchSettings = useSettingsStore((s) => s.fetchAll) - const availablePresets = PROVIDER_PRESETS + const availablePresets = PROVIDER_PRESETS.filter((p) => p.id !== 'official') const initialPreset = provider ? availablePresets.find((p) => p.id === provider.presetId) || availablePresets.at(-1)! : availablePresets[0] const [selectedPreset, setSelectedPreset] = useState(initialPreset) @@ -210,28 +233,23 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) const [settingsJson, setSettingsJson] = useState('') const [settingsJsonError, setSettingsJsonError] = useState(null) - // Load current settings.json and merge provider env (or show as-is for official) + // Load current settings.json and merge provider env vars useEffect(() => { import('../api/settings').then(({ settingsApi }) => { settingsApi.getUser().then((settings) => { - if (selectedPreset.id === 'official') { - // Official: show current settings as-is (env keys will be cleared on save) - setSettingsJson(JSON.stringify(settings, null, 2)) - } else { - const merged = { - ...settings, - env: { - ...((settings.env as Record) || {}), - ANTHROPIC_BASE_URL: baseUrl, - ANTHROPIC_AUTH_TOKEN: apiKey || '(your API key)', - ANTHROPIC_MODEL: models.main, - ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku, - ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet, - ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus, - }, - } - setSettingsJson(JSON.stringify(merged, null, 2)) + const merged = { + ...settings, + env: { + ...((settings.env as Record) || {}), + ANTHROPIC_BASE_URL: baseUrl, + ANTHROPIC_AUTH_TOKEN: apiKey || '(your API key)', + ANTHROPIC_MODEL: models.main, + ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku, + ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet, + ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus, + }, } + setSettingsJson(JSON.stringify(merged, null, 2)) }).catch(() => { setSettingsJson(JSON.stringify({}, null, 2)) }) @@ -248,8 +266,7 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) } const isCustom = selectedPreset.id === 'custom' - const isOfficial = selectedPreset.id === 'official' - const canSubmit = isOfficial || (name.trim() && baseUrl.trim() && (mode === 'edit' || apiKey.trim()) && models.main.trim() && !settingsJsonError) + const canSubmit = name.trim() && baseUrl.trim() && (mode === 'edit' || apiKey.trim()) && models.main.trim() && !settingsJsonError const handleSubmit = async () => { if (!canSubmit) return @@ -266,17 +283,6 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) } } - if (isOfficial) { - try { - await useProviderStore.getState().activateOfficial() - await fetchSettings() - } catch (err) { - console.error('Failed to activate official:', err) - } - onClose() - return - } - if (mode === 'create') { await createProvider({ presetId: selectedPreset.id, @@ -367,55 +373,50 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) setNotes(e.target.value)} placeholder="Optional notes..." /> - {/* Non-official: Base URL, API Key, Model Mapping, Test */} - {!isOfficial && ( - <> - {/* Base URL */} - {isCustom || mode === 'edit' ? ( - setBaseUrl(e.target.value)} placeholder="https://api.example.com/anthropic" /> - ) : ( -
- -
- {baseUrl} -
-
- )} - - setApiKey(e.target.value)} - placeholder={mode === 'edit' ? '****' : 'sk-...'} - /> - - {/* Model Mapping */} -
- -
- setModels({ ...models, main: e.target.value })} placeholder="Model ID" /> - setModels({ ...models, haiku: e.target.value })} placeholder="Same as main" /> - setModels({ ...models, sonnet: e.target.value })} placeholder="Same as main" /> - setModels({ ...models, opus: e.target.value })} placeholder="Same as main" /> -
+ {/* Base URL */} + {isCustom || mode === 'edit' ? ( + setBaseUrl(e.target.value)} placeholder="https://api.example.com/anthropic" /> + ) : ( +
+ +
+ {baseUrl}
- - {/* Test connection */} -
- - {testResult && ( - - {testResult.success ? `Connected (${testResult.latencyMs}ms)` : `Failed: ${testResult.error}`} - - )} -
- +
)} + setApiKey(e.target.value)} + placeholder={mode === 'edit' ? '****' : 'sk-...'} + /> + + {/* Model Mapping */} +
+ +
+ setModels({ ...models, main: e.target.value })} placeholder="Model ID" /> + setModels({ ...models, haiku: e.target.value })} placeholder="Same as main" /> + setModels({ ...models, sonnet: e.target.value })} placeholder="Same as main" /> + setModels({ ...models, opus: e.target.value })} placeholder="Same as main" /> +
+
+ + {/* Test connection */} +
+ + {testResult && ( + + {testResult.success ? `Connected (${testResult.latencyMs}ms)` : `Failed: ${testResult.error}`} + + )} +
+ {/* Settings JSON — editable, shown for all presets including official */}