diff --git a/.gitignore b/.gitignore index 91edb3de5d1..0e4afaca611 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ package-lock.json .claude .codex .worktrees/ +.atlarix/ # Qwen Code Configs .qwen/* diff --git a/packages/web-shell/client/App.tsx b/packages/web-shell/client/App.tsx index 502565a4130..e3baacbaf0b 100644 --- a/packages/web-shell/client/App.tsx +++ b/packages/web-shell/client/App.tsx @@ -2430,6 +2430,21 @@ export function App({ ); return true; } + if (modelArg === '--vision') { + setModelDialogMode('vision'); + return true; + } + if (modelArg.startsWith('--vision ')) { + const visionModelId = modelArg.replace(/^--vision\s+/, ''); + setWorkspaceSetting( + 'workspace', + 'visionModel', + visionModelId, + ).catch((error: unknown) => + reportError(error, t('model.setVision')), + ); + return true; + } if (modelArg) { if (!connectionRef.current.sessionId) { setPendingModel(modelArg); @@ -3298,6 +3313,15 @@ export function App({ [reportError, setWorkspaceSetting, t], ); + const handleVisionModelSelect = useCallback( + (modelId: string) => { + setWorkspaceSetting('workspace', 'visionModel', modelId).catch( + (error: unknown) => reportError(error, t('model.setVision')), + ); + }, + [reportError, setWorkspaceSetting, t], + ); + const commands = useMemo(() => { const skillNames = new Set(connection.skills ?? []); return mergeCommands(connection.commands ?? [], getLocalCommands(t)) @@ -3437,7 +3461,9 @@ export function App({ ? t('model.setFast') : modelDialogMode === 'voice' ? t('model.setVoice') - : t('model.select') + : modelDialogMode === 'vision' + ? t('model.setVision') + : t('model.select') } size="lg" onClose={() => setModelDialogMode(null)} @@ -3453,6 +3479,8 @@ export function App({ handleFastModelSelect(modelId); } else if (modelDialogMode === 'voice') { handleVoiceModelSelect(modelId); + } else if (modelDialogMode === 'vision') { + handleVisionModelSelect(modelId); } else { handleModelSelect(modelId); } @@ -3556,6 +3584,7 @@ export function App({ onSubDialog={(key) => { setShowSettingsDialog(false); if (key === 'fastModel') setModelDialogMode('fast'); + else if (key === 'visionModel') setModelDialogMode('vision'); else if (key === 'tools.approvalMode') setShowApprovalModeDialog(true); }} diff --git a/packages/web-shell/client/components/dialogs/ModelDialog.tsx b/packages/web-shell/client/components/dialogs/ModelDialog.tsx index 40d3a013183..dbbf6c3fa89 100644 --- a/packages/web-shell/client/components/dialogs/ModelDialog.tsx +++ b/packages/web-shell/client/components/dialogs/ModelDialog.tsx @@ -5,7 +5,7 @@ import { useListboxKeyboard } from '../../hooks/useListboxKeyboard'; import { dp } from './dialogStyles'; import styles from './ModelDialog.module.css'; -export type ModelDialogMode = 'main' | 'fast' | 'voice'; +export type ModelDialogMode = 'main' | 'fast' | 'voice' | 'vision'; interface ModelDialogProps { mode?: ModelDialogMode; @@ -107,6 +107,7 @@ export function ModelDialog({ const listRef = useRef(null); const isFastMode = mode === 'fast'; const isVoiceMode = mode === 'voice'; + const isVisionMode = mode === 'vision'; const currentIdx = availableModels.findIndex((m) => m.id === currentModel); const [activeIndex, setActiveIndex] = useState( currentIdx >= 0 ? currentIdx : 0, @@ -171,7 +172,9 @@ export function ModelDialog({ ? t('model.setFast') : isVoiceMode ? t('model.setVoice') - : t('model.select') + : isVisionMode + ? t('model.setVision') + : t('model.select') } > {availableModels.length === 0 ? ( diff --git a/packages/web-shell/client/components/messages/SettingsMessage.tsx b/packages/web-shell/client/components/messages/SettingsMessage.tsx index 1c80f300783..6438ce92719 100644 --- a/packages/web-shell/client/components/messages/SettingsMessage.tsx +++ b/packages/web-shell/client/components/messages/SettingsMessage.tsx @@ -47,7 +47,7 @@ export interface SettingsMessageSettingsState { ) => Promise; } -const SUB_DIALOG_KEYS = new Set(['fastModel']); +const SUB_DIALOG_KEYS = new Set(['fastModel', 'visionModel']); const HIDDEN_SETTING_KEYS = new Set([ 'ui.hideTips', 'ui.enableUserFeedback', diff --git a/packages/web-shell/client/constants/localCommands.ts b/packages/web-shell/client/constants/localCommands.ts index c08a1fb116a..5810023d86d 100644 --- a/packages/web-shell/client/constants/localCommands.ts +++ b/packages/web-shell/client/constants/localCommands.ts @@ -46,7 +46,7 @@ export function getLocalCommands(t: Translate): CommandInfo[] { { name: 'model', description: t('local.model'), - argumentHint: '[--fast|--voice] []', + argumentHint: '[--fast|--voice|--vision] []', }, { name: 'mcp', diff --git a/packages/web-shell/client/i18n.tsx b/packages/web-shell/client/i18n.tsx index 46579915c69..b09fb1abfea 100644 --- a/packages/web-shell/client/i18n.tsx +++ b/packages/web-shell/client/i18n.tsx @@ -962,6 +962,7 @@ const EN: Messages = { 'model.select': 'Select Model', 'model.setFast': 'Set Fast Model', 'model.setVoice': 'Set Voice Model', + 'model.setVision': 'Set Vision Model', 'model.switch': 'Switch Model', 'model.unknown': 'unknown', 'resume.current': 'current', @@ -2143,6 +2144,7 @@ const ZH: Messages = { 'model.select': '选择模型', 'model.setFast': '设置 Fast Model', 'model.setVoice': '设置语音模型', + 'model.setVision': '设置视觉模型', 'model.switch': '切换模型', 'model.unknown': '未知', 'resume.current': '当前',