| import { feature } from 'bun:bundle' |
| import { satisfies } from 'src/utils/semver.js' |
| import { isRunningWithBun } from '../utils/bundledMode.js' |
| import { getPlatform } from '../utils/platform.js' |
| import type { KeybindingBlock } from './types.js' |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| const IMAGE_PASTE_KEY = getPlatform() === 'windows' ? 'alt+v' : 'ctrl+v' |
|
|
| |
| |
| |
| |
| const SUPPORTS_TERMINAL_VT_MODE = |
| getPlatform() !== 'windows' || |
| (isRunningWithBun() |
| ? satisfies(process.versions.bun, '>=1.2.23') |
| : satisfies(process.versions.node, '>=22.17.0 <23.0.0 || >=24.2.0')) |
|
|
| |
| |
| |
| const MODE_CYCLE_KEY = SUPPORTS_TERMINAL_VT_MODE ? 'shift+tab' : 'meta+m' |
|
|
| export const DEFAULT_BINDINGS: KeybindingBlock[] = [ |
| { |
| context: 'Global', |
| bindings: { |
| |
| |
| |
| |
| 'ctrl+c': 'app:interrupt', |
| 'ctrl+d': 'app:exit', |
| 'ctrl+l': 'app:redraw', |
| 'ctrl+t': 'app:toggleTodos', |
| 'ctrl+o': 'app:toggleTranscript', |
| ...(feature('KAIROS') || feature('KAIROS_BRIEF') |
| ? { 'ctrl+shift+b': 'app:toggleBrief' as const } |
| : {}), |
| 'ctrl+shift+o': 'app:toggleTeammatePreview', |
| 'ctrl+r': 'history:search', |
| |
| |
| ...(feature('QUICK_SEARCH') |
| ? { |
| 'ctrl+shift+f': 'app:globalSearch' as const, |
| 'cmd+shift+f': 'app:globalSearch' as const, |
| 'ctrl+shift+p': 'app:quickOpen' as const, |
| 'cmd+shift+p': 'app:quickOpen' as const, |
| } |
| : {}), |
| ...(feature('TERMINAL_PANEL') ? { 'meta+j': 'app:toggleTerminal' } : {}), |
| }, |
| }, |
| { |
| context: 'Chat', |
| bindings: { |
| escape: 'chat:cancel', |
| |
| 'ctrl+x ctrl+k': 'chat:killAgents', |
| [MODE_CYCLE_KEY]: 'chat:cycleMode', |
| 'meta+p': 'chat:modelPicker', |
| 'meta+o': 'chat:fastMode', |
| 'meta+t': 'chat:thinkingToggle', |
| enter: 'chat:submit', |
| up: 'history:previous', |
| down: 'history:next', |
| |
| |
| |
| |
| 'ctrl+_': 'chat:undo', |
| 'ctrl+shift+-': 'chat:undo', |
| |
| 'ctrl+x ctrl+e': 'chat:externalEditor', |
| 'ctrl+g': 'chat:externalEditor', |
| 'ctrl+s': 'chat:stash', |
| |
| [IMAGE_PASTE_KEY]: 'chat:imagePaste', |
| ...(feature('MESSAGE_ACTIONS') |
| ? { 'shift+up': 'chat:messageActions' as const } |
| : {}), |
| |
| |
| |
| |
| |
| ...(feature('VOICE_MODE') ? { space: 'voice:pushToTalk' } : {}), |
| }, |
| }, |
| { |
| context: 'Autocomplete', |
| bindings: { |
| tab: 'autocomplete:accept', |
| escape: 'autocomplete:dismiss', |
| up: 'autocomplete:previous', |
| down: 'autocomplete:next', |
| }, |
| }, |
| { |
| context: 'Settings', |
| bindings: { |
| |
| escape: 'confirm:no', |
| |
| up: 'select:previous', |
| down: 'select:next', |
| k: 'select:previous', |
| j: 'select:next', |
| 'ctrl+p': 'select:previous', |
| 'ctrl+n': 'select:next', |
| |
| space: 'select:accept', |
| |
| enter: 'settings:close', |
| |
| '/': 'settings:search', |
| |
| r: 'settings:retry', |
| }, |
| }, |
| { |
| context: 'Confirmation', |
| bindings: { |
| y: 'confirm:yes', |
| n: 'confirm:no', |
| enter: 'confirm:yes', |
| escape: 'confirm:no', |
| |
| up: 'confirm:previous', |
| down: 'confirm:next', |
| tab: 'confirm:nextField', |
| space: 'confirm:toggle', |
| |
| 'shift+tab': 'confirm:cycleMode', |
| |
| 'ctrl+e': 'confirm:toggleExplanation', |
| |
| 'ctrl+d': 'permission:toggleDebug', |
| }, |
| }, |
| { |
| context: 'Tabs', |
| bindings: { |
| |
| tab: 'tabs:next', |
| 'shift+tab': 'tabs:previous', |
| right: 'tabs:next', |
| left: 'tabs:previous', |
| }, |
| }, |
| { |
| context: 'Transcript', |
| bindings: { |
| 'ctrl+e': 'transcript:toggleShowAll', |
| 'ctrl+c': 'transcript:exit', |
| escape: 'transcript:exit', |
| |
| |
| q: 'transcript:exit', |
| }, |
| }, |
| { |
| context: 'HistorySearch', |
| bindings: { |
| 'ctrl+r': 'historySearch:next', |
| escape: 'historySearch:accept', |
| tab: 'historySearch:accept', |
| 'ctrl+c': 'historySearch:cancel', |
| enter: 'historySearch:execute', |
| }, |
| }, |
| { |
| context: 'Task', |
| bindings: { |
| |
| |
| 'ctrl+b': 'task:background', |
| }, |
| }, |
| { |
| context: 'ThemePicker', |
| bindings: { |
| 'ctrl+t': 'theme:toggleSyntaxHighlighting', |
| }, |
| }, |
| { |
| context: 'Scroll', |
| bindings: { |
| pageup: 'scroll:pageUp', |
| pagedown: 'scroll:pageDown', |
| wheelup: 'scroll:lineUp', |
| wheeldown: 'scroll:lineDown', |
| 'ctrl+home': 'scroll:top', |
| 'ctrl+end': 'scroll:bottom', |
| |
| |
| |
| |
| |
| |
| 'ctrl+shift+c': 'selection:copy', |
| 'cmd+c': 'selection:copy', |
| }, |
| }, |
| { |
| context: 'Help', |
| bindings: { |
| escape: 'help:dismiss', |
| }, |
| }, |
| |
| { |
| context: 'Attachments', |
| bindings: { |
| right: 'attachments:next', |
| left: 'attachments:previous', |
| backspace: 'attachments:remove', |
| delete: 'attachments:remove', |
| down: 'attachments:exit', |
| escape: 'attachments:exit', |
| }, |
| }, |
| |
| { |
| context: 'Footer', |
| bindings: { |
| up: 'footer:up', |
| 'ctrl+p': 'footer:up', |
| down: 'footer:down', |
| 'ctrl+n': 'footer:down', |
| right: 'footer:next', |
| left: 'footer:previous', |
| enter: 'footer:openSelected', |
| escape: 'footer:clearSelection', |
| }, |
| }, |
| |
| { |
| context: 'MessageSelector', |
| bindings: { |
| up: 'messageSelector:up', |
| down: 'messageSelector:down', |
| k: 'messageSelector:up', |
| j: 'messageSelector:down', |
| 'ctrl+p': 'messageSelector:up', |
| 'ctrl+n': 'messageSelector:down', |
| 'ctrl+up': 'messageSelector:top', |
| 'shift+up': 'messageSelector:top', |
| 'meta+up': 'messageSelector:top', |
| 'shift+k': 'messageSelector:top', |
| 'ctrl+down': 'messageSelector:bottom', |
| 'shift+down': 'messageSelector:bottom', |
| 'meta+down': 'messageSelector:bottom', |
| 'shift+j': 'messageSelector:bottom', |
| enter: 'messageSelector:select', |
| }, |
| }, |
| |
| ...(feature('MESSAGE_ACTIONS') |
| ? [ |
| { |
| context: 'MessageActions' as const, |
| bindings: { |
| up: 'messageActions:prev' as const, |
| down: 'messageActions:next' as const, |
| k: 'messageActions:prev' as const, |
| j: 'messageActions:next' as const, |
| |
| 'meta+up': 'messageActions:top' as const, |
| 'meta+down': 'messageActions:bottom' as const, |
| 'super+up': 'messageActions:top' as const, |
| 'super+down': 'messageActions:bottom' as const, |
| |
| |
| 'shift+up': 'messageActions:prevUser' as const, |
| 'shift+down': 'messageActions:nextUser' as const, |
| escape: 'messageActions:escape' as const, |
| 'ctrl+c': 'messageActions:ctrlc' as const, |
| |
| enter: 'messageActions:enter' as const, |
| c: 'messageActions:c' as const, |
| p: 'messageActions:p' as const, |
| }, |
| }, |
| ] |
| : []), |
| |
| { |
| context: 'DiffDialog', |
| bindings: { |
| escape: 'diff:dismiss', |
| left: 'diff:previousSource', |
| right: 'diff:nextSource', |
| up: 'diff:previousFile', |
| down: 'diff:nextFile', |
| enter: 'diff:viewDetails', |
| |
| }, |
| }, |
| |
| { |
| context: 'ModelPicker', |
| bindings: { |
| left: 'modelPicker:decreaseEffort', |
| right: 'modelPicker:increaseEffort', |
| }, |
| }, |
| |
| { |
| context: 'Select', |
| bindings: { |
| up: 'select:previous', |
| down: 'select:next', |
| j: 'select:next', |
| k: 'select:previous', |
| 'ctrl+n': 'select:next', |
| 'ctrl+p': 'select:previous', |
| enter: 'select:accept', |
| escape: 'select:cancel', |
| }, |
| }, |
| |
| |
| { |
| context: 'Plugin', |
| bindings: { |
| space: 'plugin:toggle', |
| i: 'plugin:install', |
| }, |
| }, |
| ] |
|
|