From ba019c05a6a37eb2a231ae87d9919b5fd08f3332 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Fri, 15 May 2026 00:27:39 +0300 Subject: [PATCH] feat: make agent switching shortcut configurable (#1186) Adds Cycle Agent to shortcut settings with Tab as the default Applies custom shortcut in chat input and model selector Updates help dialog to show saved shortcut values --- packages/ui/src/components/chat/ChatInput.tsx | 23 ++++++-- .../ui/src/components/chat/ModelControls.tsx | 48 +++++++++++++++-- packages/ui/src/components/ui/HelpDialog.tsx | 3 +- packages/ui/src/hooks/useKeyboardShortcuts.ts | 54 ++++++++++++++++++- .../ui/src/lib/i18n/messages/en.settings.ts | 1 + packages/ui/src/lib/i18n/messages/en.ts | 2 +- .../ui/src/lib/i18n/messages/es.settings.ts | 1 + packages/ui/src/lib/i18n/messages/es.ts | 2 +- .../ui/src/lib/i18n/messages/ko.settings.ts | 1 + packages/ui/src/lib/i18n/messages/ko.ts | 2 +- .../ui/src/lib/i18n/messages/pl.settings.ts | 1 + packages/ui/src/lib/i18n/messages/pl.ts | 2 +- .../src/lib/i18n/messages/pt-BR.settings.ts | 1 + packages/ui/src/lib/i18n/messages/pt-BR.ts | 2 +- .../ui/src/lib/i18n/messages/uk.settings.ts | 1 + packages/ui/src/lib/i18n/messages/uk.ts | 2 +- .../src/lib/i18n/messages/zh-CN.settings.ts | 1 + packages/ui/src/lib/i18n/messages/zh-CN.ts | 2 +- packages/ui/src/lib/shortcuts.ts | 7 +++ 19 files changed, 139 insertions(+), 17 deletions(-) diff --git a/packages/ui/src/components/chat/ChatInput.tsx b/packages/ui/src/components/chat/ChatInput.tsx index 082b3746..3bf18760 100644 --- a/packages/ui/src/components/chat/ChatInput.tsx +++ b/packages/ui/src/components/chat/ChatInput.tsx @@ -62,6 +62,7 @@ import { useI18n } from '@/lib/i18n'; import { fetchResponseStyleInstruction } from '@/lib/responseStyle'; import { wrapSystemReminder } from '@/lib/systemReminder'; import { getSyncMessages } from '@/sync/sync-refs'; +import { eventMatchesShortcut, getEffectiveShortcutCombo, normalizeCombo } from '@/lib/shortcuts'; const MAX_VISIBLE_TEXTAREA_LINES = 8; const EMPTY_QUEUE: QueuedMessage[] = []; @@ -791,6 +792,10 @@ const ChatInputComponent: React.FC = ({ onOpenSettings, scrollTo const isExpandedInput = useUIStore((state) => state.isExpandedInput); const setExpandedInput = useUIStore((state) => state.setExpandedInput); const setTimelineDialogOpen = useUIStore((state) => state.setTimelineDialogOpen); + const cycleAgentShortcutOverride = useUIStore((state) => state.shortcutOverrides.cycle_agent); + const cycleAgentShortcut = React.useMemo(() => ( + getEffectiveShortcutCombo('cycle_agent', cycleAgentShortcutOverride ? { cycle_agent: cycleAgentShortcutOverride } : undefined) + ), [cycleAgentShortcutOverride]); const { git: runtimeGit } = useRuntimeAPIs(); const { currentTheme } = useThemeSystem(); const chatSearchDirectory = useChatSearchDirectory(); @@ -1762,9 +1767,19 @@ const ChatInputComponent: React.FC = ({ onOpenSettings, scrollTo return; } - if (e.key === 'Tab' && !showCommandAutocomplete && !showSkillAutocomplete && !showFileMention) { + const cycleAgentBackwardShortcut = cycleAgentShortcut && !cycleAgentShortcut.includes('shift') + ? normalizeCombo(`shift+${cycleAgentShortcut}`) + : ''; + const cycleAgentDirection = cycleAgentBackwardShortcut && eventMatchesShortcut(e, cycleAgentBackwardShortcut) + ? -1 + : eventMatchesShortcut(e, cycleAgentShortcut) + ? 1 + : 0; + + if (cycleAgentDirection !== 0 && !showCommandAutocomplete && !showSkillAutocomplete && !showFileMention) { e.preventDefault(); - handleCycleAgent(); + e.stopPropagation(); + handleCycleAgent(cycleAgentDirection); return; } @@ -1988,8 +2003,8 @@ const ChatInputComponent: React.FC = ({ onOpenSettings, scrollTo void abortCurrentOperation(currentSessionId || undefined); }, [abortCurrentOperation, clearAbortPrompt, currentSessionId, startAbortIndicator]); - const handleCycleAgent = React.useCallback(() => { - const nextAgentName = getCycledPrimaryAgentName(agents, currentAgentName); + const handleCycleAgent = React.useCallback((direction: 1 | -1 = 1) => { + const nextAgentName = getCycledPrimaryAgentName(agents, currentAgentName, direction); if (!nextAgentName) return; setAgent(nextAgentName); diff --git a/packages/ui/src/components/chat/ModelControls.tsx b/packages/ui/src/components/chat/ModelControls.tsx index eb431784..7a52a731 100644 --- a/packages/ui/src/components/chat/ModelControls.tsx +++ b/packages/ui/src/components/chat/ModelControls.tsx @@ -46,6 +46,7 @@ import { useIsTextTruncated } from '@/hooks/useIsTextTruncated'; import { formatEffortLabel, getCycledPrimaryAgentName, type MobileControlsPanel } from './mobileControlsUtils'; import { useI18n } from '@/lib/i18n'; import { useOpenCodeReadiness } from '@/hooks/useOpenCodeReadiness'; +import { eventMatchesShortcut, formatShortcutForDisplay, getEffectiveShortcutCombo, normalizeCombo } from '@/lib/shortcuts'; type IconComponent = IconName; @@ -429,6 +430,11 @@ export const ModelControls: React.FC = ({ const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen); const setSettingsPage = useUIStore((state) => state.setSettingsPage); const hiddenModels = useUIStore((state) => state.hiddenModels); + const cycleAgentShortcutOverride = useUIStore((state) => state.shortcutOverrides.cycle_agent); + const cycleAgentShortcut = React.useMemo(() => ( + getEffectiveShortcutCombo('cycle_agent', cycleAgentShortcutOverride ? { cycle_agent: cycleAgentShortcutOverride } : undefined) + ), [cycleAgentShortcutOverride]); + const cycleAgentShortcutLabel = React.useMemo(() => formatShortcutForDisplay(cycleAgentShortcut), [cycleAgentShortcut]); const collapsedProviderSet = React.useMemo(() => { const result = new Set(); for (const providerId of collapsedModelProviders) { @@ -1299,6 +1305,22 @@ export const ModelControls: React.FC = ({ handleAgentChange(nextAgentName, { closeModelSelector: false }); }, [agents, currentAgentName, handleAgentChange]); + const getCycleAgentDirectionFromEvent = React.useCallback((event: KeyboardEvent | React.KeyboardEvent): 1 | -1 | null => { + const cycleAgentBackwardShortcut = cycleAgentShortcut && !cycleAgentShortcut.includes('shift') + ? normalizeCombo(`shift+${cycleAgentShortcut}`) + : ''; + + if (cycleAgentBackwardShortcut && eventMatchesShortcut(event, cycleAgentBackwardShortcut)) { + return -1; + } + + if (eventMatchesShortcut(event, cycleAgentShortcut)) { + return 1; + } + + return null; + }, [cycleAgentShortcut]); + const handleProviderAndModelChange = ( providerId: string, modelId: string, @@ -2566,9 +2588,10 @@ export const ModelControls: React.FC = ({ e.stopPropagation(); keyboardOwnsModelSelectionRef.current = true; - if (e.key === 'Tab') { + const cycleAgentDirection = getCycleAgentDirectionFromEvent(e); + if (cycleAgentDirection) { e.preventDefault(); - handleCycleAgentFromModelPicker(e.shiftKey ? -1 : 1); + handleCycleAgentFromModelPicker(cycleAgentDirection); } else if (e.key === 'ArrowDown') { e.preventDefault(); setModelSelectedIndex((prev) => (prev + 1) % Math.max(1, totalItems)); @@ -2641,6 +2664,18 @@ export const ModelControls: React.FC = ({ } }; + const handleModelShortcutKeyDownCapture = (e: React.KeyboardEvent) => { + const cycleAgentDirection = getCycleAgentDirectionFromEvent(e); + if (!cycleAgentDirection) { + return; + } + + e.preventDefault(); + e.stopPropagation(); + keyboardOwnsModelSelectionRef.current = true; + handleCycleAgentFromModelPicker(cycleAgentDirection); + }; + const handleFavoriteDragEnd = (event: DragEndEvent) => { const { active, over } = event; if (!over || active.id === over.id) { @@ -2729,7 +2764,12 @@ export const ModelControls: React.FC = ({ - + {/* Search Input */}
@@ -2919,7 +2959,7 @@ export const ModelControls: React.FC = ({
{t('chat.modelControls.keyboardHintNavigate')} - {t('chat.modelControls.keyboardHintSwitchAgent')} + {t('chat.modelControls.keyboardHintSwitchAgent', { shortcut: cycleAgentShortcutLabel })} {t('chat.modelControls.keyboardHintThinking')} diff --git a/packages/ui/src/components/ui/HelpDialog.tsx b/packages/ui/src/components/ui/HelpDialog.tsx index 8ba275c8..449285ae 100644 --- a/packages/ui/src/components/ui/HelpDialog.tsx +++ b/packages/ui/src/components/ui/HelpDialog.tsx @@ -64,7 +64,8 @@ export const HelpDialog: React.FC = () => { keys: '', }, { - keys: ["Tab"], + id: 'cycle_agent', + keys: '', descriptionKey: "helpDialog.item.cycleAgent", icon: "ai-agent", }, diff --git a/packages/ui/src/hooks/useKeyboardShortcuts.ts b/packages/ui/src/hooks/useKeyboardShortcuts.ts index e66e2b2e..20b7d0e2 100644 --- a/packages/ui/src/hooks/useKeyboardShortcuts.ts +++ b/packages/ui/src/hooks/useKeyboardShortcuts.ts @@ -9,9 +9,10 @@ import { createWorktreeSession } from '@/lib/worktreeSessionCreator'; import { useConfigStore } from '@/stores/useConfigStore'; import { canUseElectronDesktopIPC, invokeDesktop, isVSCodeRuntime } from '@/lib/desktop'; import { showOpenCodeStatus } from '@/lib/openCodeStatus'; -import { eventMatchesShortcut, getEffectiveShortcutCombo } from '@/lib/shortcuts'; +import { eventMatchesShortcut, getEffectiveShortcutCombo, normalizeCombo } from '@/lib/shortcuts'; import { useDirectoryStore } from '@/stores/useDirectoryStore'; import { useProjectsStore } from '@/stores/useProjectsStore'; +import { getCycledPrimaryAgentName } from '@/components/chat/mobileControlsUtils'; export const useKeyboardShortcuts = () => { const openNewSessionDraft = useSessionUIStore((s) => s.openNewSessionDraft); @@ -101,6 +102,10 @@ export const useKeyboardShortcuts = () => { return; } + const isChatInputTarget = (target: EventTarget | null) => { + return target instanceof HTMLTextAreaElement && target.getAttribute('data-chat-input') === 'true'; + }; + if (eventMatchesShortcut(e, combo('open_command_palette'))) { e.preventDefault(); toggleCommandPalette(); @@ -200,6 +205,53 @@ export const useKeyboardShortcuts = () => { return; } + const cycleAgentCombo = combo('cycle_agent'); + const cycleAgentBackwardCombo = cycleAgentCombo && !cycleAgentCombo.includes('shift') + ? normalizeCombo(`shift+${cycleAgentCombo}`) + : ''; + const cycleAgentDirection = cycleAgentBackwardCombo && eventMatchesShortcut(e, cycleAgentBackwardCombo) + ? -1 + : eventMatchesShortcut(e, cycleAgentCombo) + ? 1 + : 0; + + if (cycleAgentDirection !== 0) { + const { + isSettingsDialogOpen, + isCommandPaletteOpen, + isHelpDialogOpen, + isSessionSwitcherOpen, + isAboutDialogOpen, + activeMainTab, + } = useUIStore.getState(); + + const hasOverlay = isSettingsDialogOpen || isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen; + if (hasOverlay || activeMainTab !== 'chat' || !isChatInputTarget(e.target)) { + return; + } + + const configState = useConfigStore.getState(); + const nextAgentName = getCycledPrimaryAgentName( + configState.getVisibleAgents(), + configState.currentAgentName, + cycleAgentDirection, + ); + + if (!nextAgentName) { + return; + } + + e.preventDefault(); + configState.setAgent(nextAgentName); + useUIStore.getState().addRecentAgent(nextAgentName); + + const sessionId = useSessionUIStore.getState().currentSessionId; + if (sessionId) { + useSelectionStore.getState().saveSessionAgentSelection(sessionId, nextAgentName); + } + return; + } + if (eventMatchesShortcut(e, combo('toggle_right_sidebar'))) { const { isMobile } = useUIStore.getState(); if (isMobile) { diff --git a/packages/ui/src/lib/i18n/messages/en.settings.ts b/packages/ui/src/lib/i18n/messages/en.settings.ts index 53ff254a..9d978e37 100644 --- a/packages/ui/src/lib/i18n/messages/en.settings.ts +++ b/packages/ui/src/lib/i18n/messages/en.settings.ts @@ -759,6 +759,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Toggle services menu', 'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'Cycle services tab', 'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Cycle theme', + 'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Cycle agent', 'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Cycle favorite model forward', 'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label': 'Cycle favorite model backward', 'settings.openchamber.keyboardShortcuts.action.expand_input.label': 'Expand input', diff --git a/packages/ui/src/lib/i18n/messages/en.ts b/packages/ui/src/lib/i18n/messages/en.ts index f3bfe4e7..e57bbfcf 100644 --- a/packages/ui/src/lib/i18n/messages/en.ts +++ b/packages/ui/src/lib/i18n/messages/en.ts @@ -1641,7 +1641,7 @@ export const dict = { 'chat.modelControls.expandProvider': 'Expand provider', 'chat.modelControls.keyboardHint': '↑↓ navigate{thinking} • Enter select • Esc close', 'chat.modelControls.keyboardHintNavigate': '↑↓ navigate', - 'chat.modelControls.keyboardHintSwitchAgent': 'Tab switch agent', + 'chat.modelControls.keyboardHintSwitchAgent': '{shortcut} switch agent', 'chat.modelControls.keyboardHintThinking': '←→ thinking', 'chat.modelControls.showThinkingModes': 'Show thinking modes', 'chat.modelControls.hideThinkingModes': 'Hide thinking modes', diff --git a/packages/ui/src/lib/i18n/messages/es.settings.ts b/packages/ui/src/lib/i18n/messages/es.settings.ts index e5dc9e72..00a93516 100644 --- a/packages/ui/src/lib/i18n/messages/es.settings.ts +++ b/packages/ui/src/lib/i18n/messages/es.settings.ts @@ -759,6 +759,7 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Mostrar u ocultar menú de servicios", "settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label": "Cambiar pestaña de servicios", "settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Cambiar tema", + "settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Cambiar agente", "settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Siguiente modelo favorito", "settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label": "Modelo favorito anterior", "settings.openchamber.keyboardShortcuts.action.expand_input.label": "Expandir entrada", diff --git a/packages/ui/src/lib/i18n/messages/es.ts b/packages/ui/src/lib/i18n/messages/es.ts index d11ca1f1..7929efa1 100644 --- a/packages/ui/src/lib/i18n/messages/es.ts +++ b/packages/ui/src/lib/i18n/messages/es.ts @@ -1607,7 +1607,7 @@ export const dict: Record = { "chat.modelControls.expandProvider": "Expandir proveedor", "chat.modelControls.keyboardHint": "↑↓ navegar{thinking} • Enter seleccionar • Esc cerrar", "chat.modelControls.keyboardHintNavigate": "↑↓ navegar", - "chat.modelControls.keyboardHintSwitchAgent": "Tab cambiar agente", + "chat.modelControls.keyboardHintSwitchAgent": "{shortcut} cambiar agente", "chat.modelControls.keyboardHintThinking": "←→ cambiar razonamiento", "chat.modelControls.showThinkingModes": "Mostrar modos de razonamiento", "chat.modelControls.hideThinkingModes": "Ocultar modos de razonamiento", diff --git a/packages/ui/src/lib/i18n/messages/ko.settings.ts b/packages/ui/src/lib/i18n/messages/ko.settings.ts index 731ce627..cc6d330e 100644 --- a/packages/ui/src/lib/i18n/messages/ko.settings.ts +++ b/packages/ui/src/lib/i18n/messages/ko.settings.ts @@ -759,6 +759,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '서비스 메뉴 토글', 'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': '서비스 탭 순환', 'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '테마 순환', + 'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '에이전트 순환', 'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '즐겨찾기 모델 앞으로 순환', 'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label': '즐겨찾기 모델 뒤로 순환', 'settings.openchamber.keyboardShortcuts.action.expand_input.label': '입력 확장', diff --git a/packages/ui/src/lib/i18n/messages/ko.ts b/packages/ui/src/lib/i18n/messages/ko.ts index df2ddcb1..86d127dd 100644 --- a/packages/ui/src/lib/i18n/messages/ko.ts +++ b/packages/ui/src/lib/i18n/messages/ko.ts @@ -1641,7 +1641,7 @@ export const dict: Record = { 'chat.modelControls.expandProvider': '펼치기 프로바이더', 'chat.modelControls.keyboardHint': '↑↓ 이동 {thinking} • Enter 선택 • Esc 닫기', 'chat.modelControls.keyboardHintNavigate': '↑↓ 이동', - 'chat.modelControls.keyboardHintSwitchAgent': 'Tab 에이전트 전환', + 'chat.modelControls.keyboardHintSwitchAgent': '{shortcut} 에이전트 전환', 'chat.modelControls.keyboardHintThinking': '←→ 추론', 'chat.modelControls.showThinkingModes': '추론 모드 표시', 'chat.modelControls.hideThinkingModes': '추론 모드 숨기기', diff --git a/packages/ui/src/lib/i18n/messages/pl.settings.ts b/packages/ui/src/lib/i18n/messages/pl.settings.ts index 585ccecc..07d3b02f 100644 --- a/packages/ui/src/lib/i18n/messages/pl.settings.ts +++ b/packages/ui/src/lib/i18n/messages/pl.settings.ts @@ -598,6 +598,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.cycle_right_sidebar_tab.label': 'Przełącz zakładkę prawego paska bocznego', 'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'Przełącz zakładkę usług', 'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Przełącz motyw', + 'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Przełącz agenta', 'settings.openchamber.keyboardShortcuts.action.expand_input.label': 'Rozwiń pole wprowadzania', 'settings.openchamber.keyboardShortcuts.action.focus_input.label': 'Skup pole wprowadzania', 'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'Nowa sesja', diff --git a/packages/ui/src/lib/i18n/messages/pl.ts b/packages/ui/src/lib/i18n/messages/pl.ts index 8aeecc74..8fb7f046 100644 --- a/packages/ui/src/lib/i18n/messages/pl.ts +++ b/packages/ui/src/lib/i18n/messages/pl.ts @@ -896,7 +896,7 @@ export const dict: Record = { 'chat.modelControls.input': 'Wejście', 'chat.modelControls.keyboardHint': '↑↓ nawigacja{thinking} • Enter wybór • Esc zamknij', 'chat.modelControls.keyboardHintNavigate': '↑↓ nawigacja', - 'chat.modelControls.keyboardHintSwitchAgent': 'Tab przełącz agenta', + 'chat.modelControls.keyboardHintSwitchAgent': '{shortcut} przełącz agenta', 'chat.modelControls.keyboardHintThinking': '←→ myślenie', 'chat.modelControls.knowledge': 'Wiedza', 'chat.modelControls.limits': 'Limity', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts b/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts index f3f52b2e..1ad334d4 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.settings.ts @@ -759,6 +759,7 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Mostrar ou ocultar menu de serviços", "settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label": "Alternar aba de serviços", "settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Alternar tema", + "settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Alternar agente", "settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Próximo modelo favorito", "settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label": "Modelo favorito anterior", "settings.openchamber.keyboardShortcuts.action.expand_input.label": "Expandir entrada", diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.ts b/packages/ui/src/lib/i18n/messages/pt-BR.ts index 93168779..8fb6a34a 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.ts @@ -1607,7 +1607,7 @@ export const dict: Record = { "chat.modelControls.expandProvider": "Expandir provedor", "chat.modelControls.keyboardHint": "↑↓ navegar{thinking} • Enter selecionar • Esc fechar", "chat.modelControls.keyboardHintNavigate": "↑↓ navegar", - "chat.modelControls.keyboardHintSwitchAgent": "Tab alternar agente", + "chat.modelControls.keyboardHintSwitchAgent": "{shortcut} alternar agente", "chat.modelControls.keyboardHintThinking": "←→ mudar raciocínio", "chat.modelControls.showThinkingModes": "Mostrar modos de raciocínio", "chat.modelControls.hideThinkingModes": "Ocultar modos de raciocínio", diff --git a/packages/ui/src/lib/i18n/messages/uk.settings.ts b/packages/ui/src/lib/i18n/messages/uk.settings.ts index 8d808044..38d261df 100644 --- a/packages/ui/src/lib/i18n/messages/uk.settings.ts +++ b/packages/ui/src/lib/i18n/messages/uk.settings.ts @@ -759,6 +759,7 @@ export const settingsDict = { "settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Перемкнути меню сервісів", "settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label": "Перемкнути вкладку сервісів", "settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Перемкнути тему", + "settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Перемкнути агента", "settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Перемкнути улюблену модель вперед", "settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label": "Перемкнути улюблену модель назад", "settings.openchamber.keyboardShortcuts.action.expand_input.label": "Розгорнути введення", diff --git a/packages/ui/src/lib/i18n/messages/uk.ts b/packages/ui/src/lib/i18n/messages/uk.ts index 782c1bcd..58aa0f85 100644 --- a/packages/ui/src/lib/i18n/messages/uk.ts +++ b/packages/ui/src/lib/i18n/messages/uk.ts @@ -1607,7 +1607,7 @@ export const dict: Record = { "chat.modelControls.expandProvider": "Розгорнути провайдера", "chat.modelControls.keyboardHint": "↑↓ навігація{thinking} • Enter вибрати • Esc закрити", "chat.modelControls.keyboardHintNavigate": "↑↓ навігація", - "chat.modelControls.keyboardHintSwitchAgent": "Tab змінити агента", + "chat.modelControls.keyboardHintSwitchAgent": "{shortcut} змінити агента", "chat.modelControls.keyboardHintThinking": "←→ мислення", "chat.modelControls.showThinkingModes": "Показати режими мислення", "chat.modelControls.hideThinkingModes": "Приховати режими мислення", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts b/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts index ee0ca6c9..bbea60ea 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.settings.ts @@ -759,6 +759,7 @@ export const settingsDict = { 'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '切换服务菜单', 'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': '轮换服务菜单标签', 'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '轮换主题', + 'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '轮换智能体', 'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '向前轮换收藏模型', 'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label': '向后轮换收藏模型', 'settings.openchamber.keyboardShortcuts.action.expand_input.label': '展开输入框', diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.ts b/packages/ui/src/lib/i18n/messages/zh-CN.ts index 24bd5827..90323bc8 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.ts @@ -1607,7 +1607,7 @@ export const dict: Record = { 'chat.modelControls.expandProvider': '展开提供商', 'chat.modelControls.keyboardHint': '↑↓ 导航{thinking} • Enter 选择 • Esc 关闭', 'chat.modelControls.keyboardHintNavigate': '↑↓ 导航', - 'chat.modelControls.keyboardHintSwitchAgent': 'Tab 切换智能体', + 'chat.modelControls.keyboardHintSwitchAgent': '{shortcut} 切换智能体', 'chat.modelControls.keyboardHintThinking': '←→ 思考', 'chat.modelControls.showThinkingModes': '显示思考模式', 'chat.modelControls.hideThinkingModes': '隐藏思考模式', diff --git a/packages/ui/src/lib/shortcuts.ts b/packages/ui/src/lib/shortcuts.ts index 813cae46..9f318ebd 100644 --- a/packages/ui/src/lib/shortcuts.ts +++ b/packages/ui/src/lib/shortcuts.ts @@ -297,6 +297,13 @@ const SHORTCUT_ACTIONS: ReadonlyArray = [ label: 'Cycle thinking variant', description: 'Cycle thinking variant while in chat', }, + { + id: 'cycle_agent', + defaultCombo: 'tab', + label: 'Cycle agent', + description: 'Cycle agent while the model selector is open', + customizable: true, + }, { id: 'cycle_favorite_model_forward', defaultCombo: 'ctrl+]',