From e9fa36ab8697c59845538cc02b709f417aff717a 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 10:54:44 +0800 Subject: [PATCH] refactor: remove Model tab, move effort level to General, fix test button in edit mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove redundant Model tab — model config is handled by Providers - Move Effort Level control to General tab - Fix Test Connection disabled in edit mode — use testProvider(id) when no new API key entered Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/scheduled_tasks.json | 9 +- desktop/src/pages/Settings.tsx | 181 +++++++-------------------------- 2 files changed, 39 insertions(+), 151 deletions(-) diff --git a/.claude/scheduled_tasks.json b/.claude/scheduled_tasks.json index cefe97df..b501d2ed 100644 --- a/.claude/scheduled_tasks.json +++ b/.claude/scheduled_tasks.json @@ -6,14 +6,7 @@ "prompt": "test prompt", "createdAt": 1775497208158, "recurring": true, - "name": "test-name", - "description": "test description", - "folder": "/test/folder", - "model": "claude-opus-4-6", - "permissionMode": "ask", - "worktree": false, - "frequency": "daily", - "scheduledTime": "09:00" + "lastFiredAt": 1775525400260 } ] } diff --git a/desktop/src/pages/Settings.tsx b/desktop/src/pages/Settings.tsx index ae307324..5ad3777d 100644 --- a/desktop/src/pages/Settings.tsx +++ b/desktop/src/pages/Settings.tsx @@ -5,10 +5,10 @@ import { useUIStore } from '../stores/uiStore' import { Modal } from '../components/shared/Modal' import { Input } from '../components/shared/Input' import { Button } from '../components/shared/Button' -import type { PermissionMode, EffortLevel, ModelInfo } from '../types/settings' +import type { PermissionMode, EffortLevel } from '../types/settings' import type { Provider, ProviderModel, UpdateProviderInput, ProviderTestResult } from '../types/provider' -type SettingsTab = 'providers' | 'model' | 'permissions' | 'general' +type SettingsTab = 'providers' | 'permissions' | 'general' export function Settings() { const [activeTab, setActiveTab] = useState('providers') @@ -31,7 +31,6 @@ export function Settings() { {/* Tab navigation */}
setActiveTab('providers')} /> - setActiveTab('model')} /> setActiveTab('permissions')} /> setActiveTab('general')} />
@@ -39,7 +38,6 @@ export function Settings() { {/* Tab content */}
{activeTab === 'providers' && } - {activeTab === 'model' && } {activeTab === 'permissions' && } {activeTab === 'general' && }
@@ -282,11 +280,18 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) const handleTest = async () => { const firstModel = models.find((m) => m.id.trim()) - if (!baseUrl.trim() || !apiKey.trim() || !firstModel) return + if (!baseUrl.trim() || !firstModel) return setIsTesting(true) setTestResult(null) try { - const result = await testConfig({ baseUrl: baseUrl.trim(), apiKey: apiKey.trim(), modelId: firstModel.id.trim() }) + let result: ProviderTestResult + if (mode === 'edit' && provider && !apiKey.trim()) { + // Edit mode without new key — test saved provider directly + result = await useProviderStore.getState().testProvider(provider.id) + } else { + if (!apiKey.trim()) return + result = await testConfig({ baseUrl: baseUrl.trim(), apiKey: apiKey.trim(), modelId: firstModel.id.trim() }) + } setTestResult(result) } catch { setTestResult({ success: false, latencyMs: 0, error: 'Request failed' }) @@ -376,7 +381,7 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) {/* Test connection */}
- {testResult && ( @@ -390,138 +395,6 @@ function ProviderFormModal({ open, onClose, mode, provider }: ProviderFormProps) ) } -// ─── Model Settings ────────────────────────────────────── - -function ModelSettings() { - const { availableModels, currentModel, effortLevel, activeProviderName, setModel, setEffort, fetchAll } = useSettingsStore() - const [customModelId, setCustomModelId] = useState('') - const [showCustom, setShowCustom] = useState(false) - - useEffect(() => { fetchAll() }, [fetchAll]) - - const handleSelectModel = async (model: ModelInfo) => { - await setModel(model.id) - } - - const handleCustomModel = async () => { - const id = customModelId.trim() - if (!id) return - await setModel(id) - setShowCustom(false) - setCustomModelId('') - } - - const MODEL_ICONS: Record = { - 'opus': 'diamond', - 'sonnet': 'auto_awesome', - 'haiku': 'bolt', - } as const - - const getModelIcon = (id: string) => { - if (id.includes('opus')) return MODEL_ICONS['opus'] - if (id.includes('sonnet')) return MODEL_ICONS['sonnet'] - if (id.includes('haiku')) return MODEL_ICONS['haiku'] - return 'smart_toy' - } - - const EFFORT_LABELS: Record = { - low: 'Low', - medium: 'Medium', - high: 'High', - max: 'Max', - } - - return ( -
-

Model

-

- Choose the AI model for new conversations. - {activeProviderName && ( - - (via {activeProviderName}) - - )} -

- -
- {availableModels.map((model) => { - const isSelected = currentModel?.id === model.id - return ( - - ) - })} - - {/* Custom model */} - {showCustom ? ( -
- setCustomModelId(e.target.value)} - placeholder="Enter model ID (e.g. claude-sonnet-4-6-20250514)" - className="flex-1 text-sm bg-transparent outline-none text-[var(--color-text-primary)] placeholder:text-[var(--color-text-tertiary)]" - onKeyDown={(e) => e.key === 'Enter' && handleCustomModel()} - /> - - -
- ) : ( - - )} -
- - {/* Effort level */} -

Effort Level

-

Controls how much computation the model uses.

-
- {(['low', 'medium', 'high', 'max'] as EffortLevel[]).map((level) => ( - - ))} -
-
- ) -} // ─── Permission Settings ────────────────────────────────────── @@ -574,12 +447,34 @@ function PermissionSettings() { // ─── General Settings ────────────────────────────────────── function GeneralSettings() { + const { effortLevel, setEffort } = useSettingsStore() + + const EFFORT_LABELS: Record = { + low: 'Low', + medium: 'Medium', + high: 'High', + max: 'Max', + } + return (
-

General

-

- API configuration is now managed through the Providers tab. -

+

Effort Level

+

Controls how much computation the model uses.

+
+ {(['low', 'medium', 'high', 'max'] as EffortLevel[]).map((level) => ( + + ))} +
) }