feat(coding-agent): make scoped models and tree filter shortcuts configurable (#3343)
- Add app.models.{save,enableAll,clearAll,toggleProvider,reorderUp,reorderDown}
- Add app.tree.filter.{default,noTools,userOnly,labeledOnly,all,cycleForward,cycleBackward}
- Migrate scoped-models-selector cancel to tui.select.cancel
- Prefer reserved actions on key collision in extension shortcut conflict check
This commit is contained in:
@@ -84,6 +84,10 @@ const buildBuiltinKeybindings = (resolvedKeybindings: KeybindingsConfig): BuiltI
|
||||
const restrictOverride = (RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS as readonly string[]).includes(keybinding);
|
||||
for (const key of keyList) {
|
||||
const normalizedKey = key.toLowerCase() as KeyId;
|
||||
// If multiple actions bind the same key, the reserved action wins so extensions
|
||||
// remain blocked by reserved shortcuts regardless of iteration order.
|
||||
const existing = builtinKeybindings[normalizedKey];
|
||||
if (existing?.restrictOverride && !restrictOverride) continue;
|
||||
builtinKeybindings[normalizedKey] = {
|
||||
keybinding,
|
||||
restrictOverride,
|
||||
|
||||
@@ -39,6 +39,19 @@ export interface AppKeybindings {
|
||||
"app.session.rename": true;
|
||||
"app.session.delete": true;
|
||||
"app.session.deleteNoninvasive": true;
|
||||
"app.models.save": true;
|
||||
"app.models.enableAll": true;
|
||||
"app.models.clearAll": true;
|
||||
"app.models.toggleProvider": true;
|
||||
"app.models.reorderUp": true;
|
||||
"app.models.reorderDown": true;
|
||||
"app.tree.filter.default": true;
|
||||
"app.tree.filter.noTools": true;
|
||||
"app.tree.filter.userOnly": true;
|
||||
"app.tree.filter.labeledOnly": true;
|
||||
"app.tree.filter.all": true;
|
||||
"app.tree.filter.cycleForward": true;
|
||||
"app.tree.filter.cycleBackward": true;
|
||||
}
|
||||
|
||||
export type AppKeybinding = keyof AppKeybindings;
|
||||
@@ -134,6 +147,58 @@ export const KEYBINDINGS = {
|
||||
defaultKeys: "ctrl+backspace",
|
||||
description: "Delete session when query is empty",
|
||||
},
|
||||
"app.models.save": {
|
||||
defaultKeys: "ctrl+s",
|
||||
description: "Save model selection",
|
||||
},
|
||||
"app.models.enableAll": {
|
||||
defaultKeys: "ctrl+a",
|
||||
description: "Enable all models",
|
||||
},
|
||||
"app.models.clearAll": {
|
||||
defaultKeys: "ctrl+x",
|
||||
description: "Clear all models",
|
||||
},
|
||||
"app.models.toggleProvider": {
|
||||
defaultKeys: "ctrl+p",
|
||||
description: "Toggle all models for provider",
|
||||
},
|
||||
"app.models.reorderUp": {
|
||||
defaultKeys: "alt+up",
|
||||
description: "Move model up in order",
|
||||
},
|
||||
"app.models.reorderDown": {
|
||||
defaultKeys: "alt+down",
|
||||
description: "Move model down in order",
|
||||
},
|
||||
"app.tree.filter.default": {
|
||||
defaultKeys: "ctrl+d",
|
||||
description: "Tree filter: default view",
|
||||
},
|
||||
"app.tree.filter.noTools": {
|
||||
defaultKeys: "ctrl+t",
|
||||
description: "Tree filter: hide tool results",
|
||||
},
|
||||
"app.tree.filter.userOnly": {
|
||||
defaultKeys: "ctrl+u",
|
||||
description: "Tree filter: user messages only",
|
||||
},
|
||||
"app.tree.filter.labeledOnly": {
|
||||
defaultKeys: "ctrl+l",
|
||||
description: "Tree filter: labeled entries only",
|
||||
},
|
||||
"app.tree.filter.all": {
|
||||
defaultKeys: "ctrl+a",
|
||||
description: "Tree filter: show all entries",
|
||||
},
|
||||
"app.tree.filter.cycleForward": {
|
||||
defaultKeys: "ctrl+o",
|
||||
description: "Tree filter: cycle forward",
|
||||
},
|
||||
"app.tree.filter.cycleBackward": {
|
||||
defaultKeys: "shift+ctrl+o",
|
||||
description: "Tree filter: cycle backward",
|
||||
},
|
||||
} as const satisfies KeybindingDefinitions;
|
||||
|
||||
const KEYBINDING_NAME_MIGRATIONS = {
|
||||
|
||||
Reference in New Issue
Block a user