From 2e92ba31166ab5302432a8d2e4ec6df3a52c545f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Tue, 7 Apr 2026 11:54:11 +0800 Subject: [PATCH] fix: official preset in chips, model mapping always visible, settings.json preview - Move Official to first preset chip instead of standalone card - Show model mapping directly without collapsible - Add settings.json preview showing the env vars that will be written - Official preset shows "no config needed" message Co-Authored-By: Claude Opus 4.6 (1M context) --- desktop/src/pages/Settings.tsx | 154 +++++++++++++++++---------------- 1 file changed, 78 insertions(+), 76 deletions(-) diff --git a/desktop/src/pages/Settings.tsx b/desktop/src/pages/Settings.tsx index ef9150d1..b1d444e3 100644 --- a/desktop/src/pages/Settings.tsx +++ b/desktop/src/pages/Settings.tsx @@ -115,27 +115,6 @@ function ProviderSettings() { - {/* Official provider card */} -
!isOfficialActive && handleActivateOfficial()} - > - -
-
- Claude Official - {isOfficialActive && ( - ACTIVE - )} -
-
Anthropic native — no API key required
-
-
- {/* Saved providers */} {isLoading && providers.length === 0 ? (
@@ -216,7 +195,7 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) const { createProvider, updateProvider, testConfig } = useProviderStore() const fetchSettings = useSettingsStore((s) => s.fetchAll) - const availablePresets = PROVIDER_PRESETS.filter((p) => p.id !== 'official') + const availablePresets = PROVIDER_PRESETS const initialPreset = provider ? availablePresets.find((p) => p.id === provider.presetId) || availablePresets.at(-1)! : availablePresets[0] const [selectedPreset, setSelectedPreset] = useState(initialPreset) @@ -225,7 +204,6 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) const [apiKey, setApiKey] = useState('') const [notes, setNotes] = useState(provider?.notes ?? '') const [models, setModels] = useState(provider?.models ?? { ...initialPreset.defaultModels }) - const [showAdvanced, setShowAdvanced] = useState(false) const [isSubmitting, setIsSubmitting] = useState(false) const [testResult, setTestResult] = useState(null) const [isTesting, setIsTesting] = useState(false) @@ -239,12 +217,19 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) } const isCustom = selectedPreset.id === 'custom' - const canSubmit = name.trim() && baseUrl.trim() && (mode === 'edit' || apiKey.trim()) && models.main.trim() + const isOfficial = selectedPreset.id === 'official' + const canSubmit = isOfficial || (name.trim() && baseUrl.trim() && (mode === 'edit' || apiKey.trim()) && models.main.trim()) const handleSubmit = async () => { if (!canSubmit) return setIsSubmitting(true) try { + if (isOfficial) { + await useProviderStore.getState().activateOfficial() + await fetchSettings() + onClose() + return + } if (mode === 'create') { await createProvider({ presetId: selectedPreset.id, @@ -309,7 +294,7 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) } >
- {/* Preset chips (create mode only) */} + {/* Preset chips */} {mode === 'create' && (
@@ -331,63 +316,80 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps)
)} - setName(e.target.value)} placeholder="Provider name" /> - - {/* Base URL — always visible for custom, read-only hint for presets */} - {isCustom || mode === 'edit' ? ( - setBaseUrl(e.target.value)} placeholder="https://api.example.com/anthropic" /> - ) : ( -
- -
- {baseUrl} -
+ {/* Official — no config needed */} + {isOfficial && mode === 'create' ? ( +
+ Official provider uses Anthropic native login — no API key or configuration needed.
- )} + ) : ( + <> + setName(e.target.value)} placeholder="Provider name" /> - setApiKey(e.target.value)} - placeholder={mode === 'edit' ? '****' : 'sk-...'} - /> + {/* Base URL */} + {isCustom || mode === 'edit' ? ( + setBaseUrl(e.target.value)} placeholder="https://api.example.com/anthropic" /> + ) : ( +
+ +
+ {baseUrl} +
+
+ )} - setNotes(e.target.value)} placeholder="Optional notes..." /> + setApiKey(e.target.value)} + placeholder={mode === 'edit' ? '****' : 'sk-...'} + /> - {/* Advanced: Model Mapping */} -
- - {showAdvanced && ( -
- 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" /> + setNotes(e.target.value)} placeholder="Optional notes..." /> + + {/* Model Mapping — always visible */} +
+ +
+ 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}`} - - )} -
+ {/* Test connection */} +
+ + {testResult && ( + + {testResult.success ? `Connected (${testResult.latencyMs}ms)` : `Failed: ${testResult.error}`} + + )} +
+ + {/* Settings JSON Preview */} +
+ +
+{JSON.stringify({
+  env: {
+    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 || '...',
+  },
+}, null, 2)}
+              
+

Will be written to ~/.claude/settings.json on activation.

+
+ + )}
)