@kolisachint/hoocode-agent 0.5.56 → 0.5.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/core/keybindings.d.ts +2 -12
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +5 -16
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +1 -1
- package/dist/core/settings-defaults.d.ts.map +1 -1
- package/dist/core/settings-defaults.js +1 -1
- package/dist/core/settings-defaults.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tool-output-view.d.ts +28 -10
- package/dist/core/tool-output-view.d.ts.map +1 -1
- package/dist/core/tool-output-view.js +24 -9
- package/dist/core/tool-output-view.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/plugins.d.ts.map +1 -1
- package/dist/core/tools/plugins.js +2 -1
- package/dist/core/tools/plugins.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/search.d.ts.map +1 -1
- package/dist/core/tools/search.js +2 -1
- package/dist/core/tools/search.js.map +1 -1
- package/dist/core/tools/webfetch.d.ts.map +1 -1
- package/dist/core/tools/webfetch.js +2 -1
- package/dist/core/tools/webfetch.js.map +1 -1
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js +2 -1
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/modes/interactive/command-executor.d.ts.map +1 -1
- package/dist/modes/interactive/command-executor.js +2 -5
- package/dist/modes/interactive/command-executor.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +3 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-chain-summary.d.ts +2 -1
- package/dist/modes/interactive/components/tool-chain-summary.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chain-summary.js +2 -1
- package/dist/modes/interactive/components/tool-chain-summary.js.map +1 -1
- package/dist/modes/interactive/components/tool-chain.d.ts +2 -9
- package/dist/modes/interactive/components/tool-chain.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chain.js +3 -20
- package/dist/modes/interactive/components/tool-chain.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +16 -20
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +38 -37
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-signal.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-signal.js +1 -1
- package/dist/modes/interactive/components/tool-signal.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +28 -20
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +57 -68
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/keybindings.md +3 -1
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.57] - 2026-09-04
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **The tool output dial is three stops and two keys, and `full` finally means
|
|
8
|
+
full.** It had grown into three separate ideas: a dial (`alt+o`) with a
|
|
9
|
+
`radar` / `glance` / `full` scale, an all-or-nothing expand (`ctrl+o`), and a
|
|
10
|
+
one-at-a-time unfold (`alt+u` / `shift+alt+u`) that peeled backwards from the
|
|
11
|
+
newest block and meant something different in each view. Three states to hold,
|
|
12
|
+
and a `full` stop that was not full — `ctrl+o` was what made it full.
|
|
13
|
+
|
|
14
|
+
Now there is one value. The dial reads **radar → peek → full**: one line per
|
|
15
|
+
run of calls, the call line with the first few lines of its result, the same
|
|
16
|
+
with nothing trimmed. `glance` is gone as a stop — a handful of result lines
|
|
17
|
+
answers "did this find anything" better than a folded body did, so `peek`
|
|
18
|
+
replaces it as the default, and `PEEK_LINES` is the single knob every renderer
|
|
19
|
+
trims to (including tools with no renderer of their own, which used to print
|
|
20
|
+
their whole result whatever the dial said).
|
|
21
|
+
|
|
22
|
+
`ctrl+o` still exists and is still the reflex key: from any stop it jumps
|
|
23
|
+
straight to `full`, and pressing it again returns to the stop it came from.
|
|
24
|
+
The header, compaction and branch summaries and skill blocks follow it, since
|
|
25
|
+
`full` means nothing is held back. The two keys differ in what they remember:
|
|
26
|
+
`alt+o` saves where it lands, `ctrl+o` does not.
|
|
27
|
+
|
|
28
|
+
`alt+u` and `shift+alt+u` are gone, and with them the per-chain opened state,
|
|
29
|
+
the per-block revealed flag and the "a revealed block leaves radar while it is
|
|
30
|
+
open" special case. A run of calls is a summary line in radar and its own calls
|
|
31
|
+
at every other stop; nothing opens one chain or one block on its own any more.
|
|
32
|
+
Old `toolOutputView` settings still load: `glance` becomes `peek`, `collapsed`
|
|
33
|
+
becomes `radar`, `standard` becomes `full`, and a config that still says `peek`
|
|
34
|
+
needs no migration at all — it names a live stop again.
|
|
35
|
+
|
|
3
36
|
## [0.5.56] - 2026-09-04
|
|
4
37
|
|
|
5
38
|
### Added
|
|
@@ -11,8 +11,6 @@ interface AppKeybindings {
|
|
|
11
11
|
"app.tools.expand": true;
|
|
12
12
|
"app.view.cycleForward": true;
|
|
13
13
|
"app.view.cycleBackward": true;
|
|
14
|
-
"app.tools.unfoldOne": true;
|
|
15
|
-
"app.tools.foldOne": true;
|
|
16
14
|
"app.thinking.toggle": true;
|
|
17
15
|
"app.tasks.cycleView": true;
|
|
18
16
|
"app.team.focus": true;
|
|
@@ -253,24 +251,16 @@ export declare const KEYBINDINGS: {
|
|
|
253
251
|
};
|
|
254
252
|
readonly "app.tools.expand": {
|
|
255
253
|
readonly defaultKeys: "ctrl+o";
|
|
256
|
-
readonly description: "
|
|
254
|
+
readonly description: "Jump to the full view from wherever you are, and back again";
|
|
257
255
|
};
|
|
258
256
|
readonly "app.view.cycleForward": {
|
|
259
257
|
readonly defaultKeys: "alt+o";
|
|
260
|
-
readonly description: "Cycle tool output view (radar →
|
|
258
|
+
readonly description: "Cycle tool output view (radar → peek → full)";
|
|
261
259
|
};
|
|
262
260
|
readonly "app.view.cycleBackward": {
|
|
263
261
|
readonly defaultKeys: "shift+alt+o";
|
|
264
262
|
readonly description: "Cycle tool output view backward";
|
|
265
263
|
};
|
|
266
|
-
readonly "app.tools.unfoldOne": {
|
|
267
|
-
readonly defaultKeys: "alt+u";
|
|
268
|
-
readonly description: "Open the newest folded thing — a chain in radar, a tool body otherwise";
|
|
269
|
-
};
|
|
270
|
-
readonly "app.tools.foldOne": {
|
|
271
|
-
readonly defaultKeys: "shift+alt+u";
|
|
272
|
-
readonly description: "Re-fold the most recently opened chain or tool block";
|
|
273
|
-
};
|
|
274
264
|
readonly "app.thinking.toggle": {
|
|
275
265
|
readonly defaultKeys: "ctrl+t";
|
|
276
266
|
readonly description: "Toggle thinking blocks";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Keybinding,\n\ttype KeybindingDefinitions,\n\ttype KeybindingsConfig,\n\ttype KeyId,\n\tTUI_KEYBINDINGS,\n\tKeybindingsManager as TuiKeybindingsManager,\n} from \"@kolisachint/hoocode-tui\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\n\ninterface AppKeybindings {\n\t\"app.interrupt\": true;\n\t\"app.clear\": true;\n\t\"app.exit\": true;\n\t\"app.suspend\": true;\n\t\"app.thinking.cycle\": true;\n\t\"app.model.cycleForward\": true;\n\t\"app.model.cycleBackward\": true;\n\t\"app.model.select\": true;\n\t\"app.tools.expand\": true;\n\t\"app.view.cycleForward\": true;\n\t\"app.view.cycleBackward\": true;\n\t\"app.tools.unfoldOne\": true;\n\t\"app.tools.foldOne\": true;\n\t\"app.thinking.toggle\": true;\n\t\"app.tasks.cycleView\": true;\n\t\"app.team.focus\": true;\n\t\"app.team.nudge\": true;\n\t\"app.team.attach\": true;\n\t\"app.session.toggleNamedFilter\": true;\n\t\"app.editor.external\": true;\n\t\"app.message.followUp\": true;\n\t\"app.message.dequeue\": true;\n\t\"app.clipboard.pasteImage\": true;\n\t\"app.input.voiceTranscribe\": true;\n\t\"app.session.new\": true;\n\t\"app.session.tree\": true;\n\t\"app.session.fork\": true;\n\t\"app.session.resume\": true;\n\t\"app.session.changeDirectory\": true;\n\t\"app.session.color.cycleForward\": true;\n\t\"app.session.color.cycleBackward\": true;\n\t\"app.settings.open\": true;\n\t\"app.hotkeys.open\": true;\n\t\"app.mode.cycle\": true;\n\t\"app.tree.foldOrUp\": true;\n\t\"app.tree.unfoldOrDown\": true;\n\t\"app.tree.editLabel\": true;\n\t\"app.tree.toggleLabelTimestamp\": true;\n\t\"app.session.togglePath\": true;\n\t\"app.session.toggleSort\": true;\n\t\"app.session.rename\": true;\n\t\"app.session.delete\": true;\n\t\"app.session.deleteNoninvasive\": true;\n\t\"app.models.save\": true;\n\t\"app.models.enableAll\": true;\n\t\"app.models.clearAll\": true;\n\t\"app.models.toggleProvider\": true;\n\t\"app.models.reorderUp\": true;\n\t\"app.models.reorderDown\": true;\n\t\"app.tree.filter.default\": true;\n\t\"app.tree.filter.noTools\": true;\n\t\"app.tree.filter.userOnly\": true;\n\t\"app.tree.filter.labeledOnly\": true;\n\t\"app.tree.filter.all\": true;\n\t\"app.tree.filter.cycleForward\": true;\n\t\"app.tree.filter.cycleBackward\": true;\n}\n\nexport type AppKeybinding = keyof AppKeybindings;\n\ndeclare module \"@kolisachint/hoocode-tui\" {\n\tinterface Keybindings extends AppKeybindings {}\n}\n\n/**\n * The cockpit layout.\n *\n * Three rings, and which ring a key belongs to is decided by its modifier:\n *\n * - **ctrl — the view.** What is on screen right now: expand, thinking blocks,\n * task panel, model cycling. Pressed many times a minute, so they sit under\n * the hand and never require a second modifier.\n * - **alt — the cockpit.** What the agent *is* and where it works: model,\n * mode, working directory, settings, sessions. Pressed a few times a session.\n * - **overlays.** Inside a picker, the query line is a text field, so every\n * `ctrl+<letter>` there belongs to the *text* (ctrl+a start of line, ctrl+u\n * kill line, ctrl+w kill word). A picker's own verbs are therefore all on\n * `alt+<letter>`, mnemonic to that picker; the picker captures keys while it\n * is open, so reusing a global letter there is unambiguous.\n *\n * Two rules keep the set learnable: shift reverses whatever the unshifted key\n * does, and no binding takes a key the editor or the terminal already owns\n * (ctrl+a/e/b/f/k/u/w/y/d/l/r/g, ctrl+s XOFF, ctrl+m == enter, ctrl+i == tab).\n *\n * Two constraints from the key parser shape which alt keys are usable at all,\n * and `test/keybinding-layout.test.ts` holds both:\n *\n * - Only `alt+<letter>` and `alt+<digit>` survive a terminal without the Kitty\n * keyboard protocol. `alt+[` and `alt+]` arrive as the CSI and OSC\n * introducers and are not parsed as keys; nor is any shift-modified key, so a\n * `shift+…` default is a Kitty-only convenience on top of an unshifted key\n * that works everywhere (as `shift+ctrl+p` has always been).\n * - Legacy `alt+p` and `alt+n` are also accepted as `alt+up` and `alt+down`\n * (the emacs previous/next aliases), so no scope may bind both halves of\n * either pair.\n */\nexport const KEYBINDINGS = {\n\t...TUI_KEYBINDINGS,\n\t\"app.interrupt\": { defaultKeys: \"escape\", description: \"Cancel or abort\" },\n\t\"app.clear\": { defaultKeys: \"ctrl+c\", description: \"Clear editor\" },\n\t\"app.exit\": { defaultKeys: \"ctrl+d\", description: \"Exit when editor is empty\" },\n\t\"app.suspend\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? [] : \"ctrl+z\",\n\t\tdescription: \"Suspend to background\",\n\t},\n\t\"app.thinking.cycle\": {\n\t\tdefaultKeys: \"shift+tab\",\n\t\tdescription: \"Cycle thinking level\",\n\t},\n\t\"app.model.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Cycle to next model\",\n\t},\n\t\"app.model.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+p\",\n\t\tdescription: \"Cycle to previous model\",\n\t},\n\t// alt+m, not ctrl+l: ctrl+l is \"clear the screen\" in every shell and every\n\t// full-screen terminal app, and users press it reflexively to tidy up. It\n\t// opening a model dialog is the single most surprising key in the old set.\n\t\"app.model.select\": { defaultKeys: \"alt+m\", description: \"Open model selector\" },\n\t\"app.tools.expand\": {\n\t\tdefaultKeys: \"ctrl+o\",\n\t\tdescription: \"Expand or collapse what is in front of you (tool bodies, header, summaries)\",\n\t},\n\t// The view dial pairs with ctrl+o on purpose: same letter, different ring.\n\t// ctrl+o opens what is already there; alt+o decides how much is ever there.\n\t\"app.view.cycleForward\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Cycle tool output view (radar → glance → full)\",\n\t},\n\t\"app.view.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+o\",\n\t\tdescription: \"Cycle tool output view backward\",\n\t},\n\t// The one-at-a-time counterpart to ctrl+o's all-or-nothing. The transcript is\n\t// bottom-anchored with no app-level scrolling — anything far enough up is in\n\t// the terminal's own scrollback, which this process cannot address — so \"open\n\t// one\" can only ever mean \"open one at the tail\". Repeating the key peels\n\t// backwards from there.\n\t\"app.tools.unfoldOne\": {\n\t\tdefaultKeys: \"alt+u\",\n\t\tdescription: \"Open the newest folded thing — a chain in radar, a tool body otherwise\",\n\t},\n\t\"app.tools.foldOne\": {\n\t\tdefaultKeys: \"shift+alt+u\",\n\t\tdescription: \"Re-fold the most recently opened chain or tool block\",\n\t},\n\t\"app.thinking.toggle\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Toggle thinking blocks\",\n\t},\n\t\"app.tasks.cycleView\": {\n\t\t// ctrl+n is free in the main editor (no emacs next-line binding here).\n\t\tdefaultKeys: \"ctrl+n\",\n\t\tdescription: \"Cycle task panel view (tasks → subagents → teams, skips empty lenses)\",\n\t},\n\t\"app.team.focus\": {\n\t\t// Pairs with ctrl+n (cycle task panel view): alt+n steps INTO the teams\n\t\t// lens and focuses the role roster (--team only). Not shift+ctrl+n —\n\t\t// Windows Terminal intercepts that as its \"new window\" shortcut, the\n\t\t// same trap that moved app.tasks.cycleView off ctrl+shift+t.\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Focus the team roster (navigate roles, n nudge, a attach)\",\n\t},\n\t\"app.team.nudge\": {\n\t\t// Plain letters are safe here: these fire only while the task panel holds\n\t\t// focus (team-focus mode), never while typing in the editor.\n\t\tdefaultKeys: \"n\",\n\t\tdescription: \"Nudge the selected team role (team focus mode)\",\n\t},\n\t\"app.team.attach\": {\n\t\tdefaultKeys: \"a\",\n\t\tdescription: \"Attach to the selected team role (team focus mode)\",\n\t},\n\t// alt+e, not ctrl+g: ctrl+g is emacs/readline \"abort\" — the key you hit to\n\t// get out of something. Having it launch $EDITOR inverts that reflex.\n\t\"app.editor.external\": {\n\t\tdefaultKeys: \"alt+e\",\n\t\tdescription: \"Open external editor\",\n\t},\n\t\"app.message.followUp\": {\n\t\tdefaultKeys: \"alt+enter\",\n\t\tdescription: \"Queue follow-up message\",\n\t},\n\t\"app.message.dequeue\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Restore queued messages\",\n\t},\n\t\"app.clipboard.pasteImage\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? \"alt+v\" : \"ctrl+v\",\n\t\tdescription: \"Paste image from clipboard\",\n\t},\n\t// alt+r, not ctrl+r: ctrl+r is reverse history search in every shell, and it\n\t// was also the session picker's rename key — one chord, two meanings.\n\t\"app.input.voiceTranscribe\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Record voice and transcribe into the editor\",\n\t},\n\t// The two destructive-ish session moves stay unbound by default. /new\n\t// replaces the transcript and /fork needs a message picked out of it, so\n\t// neither wants to be one stray chord away; both remain bindable by hand.\n\t\"app.session.new\": { defaultKeys: [], description: \"Start a new session\" },\n\t\"app.session.fork\": { defaultKeys: [], description: \"Fork current session\" },\n\t// Navigation is non-destructive, so it gets keys: t for tree, h for history.\n\t\"app.session.tree\": { defaultKeys: \"alt+t\", description: \"Open session tree\" },\n\t\"app.session.resume\": { defaultKeys: \"alt+h\", description: \"Resume a session from history\" },\n\t\"app.session.changeDirectory\": {\n\t\tdefaultKeys: \"alt+w\",\n\t\tdescription: \"Change working directory (move to another repo without quitting)\",\n\t},\n\t// alt+c (\"colour\"), and the tree's filter cycle has the same letter on\n\t// purpose: the tree captures keys while it is open, so the two are never live\n\t// at once, and both mean \"step to the next one\" wherever you press them. The\n\t// backward half needs Kitty, like every other shift-modified default here.\n\t\"app.session.color.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Cycle the session chip's color\",\n\t},\n\t\"app.session.color.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Cycle the session chip's color backward\",\n\t},\n\t\"app.settings.open\": { defaultKeys: \"alt+s\", description: \"Open settings\" },\n\t\"app.hotkeys.open\": { defaultKeys: \"alt+k\", description: \"Show keyboard shortcuts\" },\n\t\"app.mode.cycle\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Cycle agent mode (ask → plan → build → debug)\",\n\t},\n\t\"app.tree.foldOrUp\": {\n\t\tdefaultKeys: [\"ctrl+left\", \"alt+left\"],\n\t\tdescription: \"Fold tree branch or move up\",\n\t},\n\t\"app.tree.unfoldOrDown\": {\n\t\tdefaultKeys: [\"ctrl+right\", \"alt+right\"],\n\t\tdescription: \"Unfold tree branch or move down\",\n\t},\n\t\"app.tree.editLabel\": {\n\t\tdefaultKeys: \"shift+l\",\n\t\tdescription: \"Edit tree label\",\n\t},\n\t\"app.tree.toggleLabelTimestamp\": {\n\t\tdefaultKeys: \"shift+t\",\n\t\tdescription: \"Toggle tree label timestamps\",\n\t},\n\t// Session picker verbs. All on alt so the picker's query line keeps the\n\t// emacs editing keys it used to lose: ctrl+a jumped to the start of the\n\t// query *and* enabled every model, ctrl+d deleted a character *and* deleted\n\t// the highlighted session.\n\t\"app.session.togglePath\": {\n\t\tdefaultKeys: \"alt+p\",\n\t\tdescription: \"Toggle session path display\",\n\t},\n\t\"app.session.toggleSort\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Toggle session sort order\",\n\t},\n\t\"app.session.rename\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Rename session\",\n\t},\n\t\"app.session.toggleNamedFilter\": {\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Toggle named session filter\",\n\t},\n\t\"app.session.delete\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Delete session\",\n\t},\n\t\"app.session.deleteNoninvasive\": {\n\t\tdefaultKeys: \"ctrl+backspace\",\n\t\tdescription: \"Delete session when query is empty\",\n\t},\n\t// Model picker verbs, same rule. ctrl+s in particular was XOFF: on a terminal\n\t// with flow control still on, \"save\" froze the session instead.\n\t\"app.models.save\": {\n\t\tdefaultKeys: \"alt+s\",\n\t\tdescription: \"Save model selection\",\n\t},\n\t\"app.models.enableAll\": {\n\t\tdefaultKeys: \"alt+a\",\n\t\tdescription: \"Enable all models\",\n\t},\n\t\"app.models.clearAll\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Clear all models\",\n\t},\n\t// alt+g (\"group\"), not alt+p: on a terminal without the Kitty protocol, alt+p\n\t// arrives as ESC-p, which the key parser also accepts as alt+up — and alt+up\n\t// is this same picker's reorder key.\n\t\"app.models.toggleProvider\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Toggle all models for provider\",\n\t},\n\t\"app.models.reorderUp\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Move model up in order\",\n\t},\n\t\"app.models.reorderDown\": {\n\t\tdefaultKeys: \"alt+down\",\n\t\tdescription: \"Move model down in order\",\n\t},\n\t\"app.options.next\": { defaultKeys: \"right\", description: \"Confirm and advance to the next question\" },\n\t\"app.options.back\": { defaultKeys: \"left\", description: \"Go back to the previous question\" },\n\t// Five lenses in a fixed order, so they are numbered rather than lettered:\n\t// alt+1..alt+5 needs no mnemonic and collides with nothing. The old set\n\t// (ctrl+d/t/u/l/a) collided with delete-char, thinking, kill-to-start,\n\t// clear-screen and start-of-line respectively.\n\t\"app.tree.filter.default\": {\n\t\tdefaultKeys: \"alt+1\",\n\t\tdescription: \"Tree filter: default view\",\n\t},\n\t\"app.tree.filter.noTools\": {\n\t\tdefaultKeys: \"alt+2\",\n\t\tdescription: \"Tree filter: hide tool results\",\n\t},\n\t\"app.tree.filter.userOnly\": {\n\t\tdefaultKeys: \"alt+3\",\n\t\tdescription: \"Tree filter: user messages only\",\n\t},\n\t\"app.tree.filter.labeledOnly\": {\n\t\tdefaultKeys: \"alt+4\",\n\t\tdescription: \"Tree filter: labeled entries only\",\n\t},\n\t\"app.tree.filter.all\": {\n\t\tdefaultKeys: \"alt+5\",\n\t\tdescription: \"Tree filter: show all entries\",\n\t},\n\t// alt+c for \"cycle\". Not a bracket pair, tempting as `alt+[` / `alt+]` are:\n\t// without the Kitty protocol those arrive as ESC-[ and ESC-], which are the\n\t// CSI and OSC introducers and so are not parsed as keys at all. The backward\n\t// half needs Kitty, like every other shift-modified default here.\n\t\"app.tree.filter.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Tree filter: cycle forward\",\n\t},\n\t\"app.tree.filter.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Tree filter: cycle backward\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nconst KEYBINDING_NAME_MIGRATIONS = {\n\tcursorUp: \"tui.editor.cursorUp\",\n\tcursorDown: \"tui.editor.cursorDown\",\n\tcursorLeft: \"tui.editor.cursorLeft\",\n\tcursorRight: \"tui.editor.cursorRight\",\n\tcursorWordLeft: \"tui.editor.cursorWordLeft\",\n\tcursorWordRight: \"tui.editor.cursorWordRight\",\n\tcursorLineStart: \"tui.editor.cursorLineStart\",\n\tcursorLineEnd: \"tui.editor.cursorLineEnd\",\n\tjumpForward: \"tui.editor.jumpForward\",\n\tjumpBackward: \"tui.editor.jumpBackward\",\n\tpageUp: \"tui.editor.pageUp\",\n\tpageDown: \"tui.editor.pageDown\",\n\tdeleteCharBackward: \"tui.editor.deleteCharBackward\",\n\tdeleteCharForward: \"tui.editor.deleteCharForward\",\n\tdeleteWordBackward: \"tui.editor.deleteWordBackward\",\n\tdeleteWordForward: \"tui.editor.deleteWordForward\",\n\tdeleteToLineStart: \"tui.editor.deleteToLineStart\",\n\tdeleteToLineEnd: \"tui.editor.deleteToLineEnd\",\n\tyank: \"tui.editor.yank\",\n\tyankPop: \"tui.editor.yankPop\",\n\tundo: \"tui.editor.undo\",\n\tnewLine: \"tui.input.newLine\",\n\tsubmit: \"tui.input.submit\",\n\ttab: \"tui.input.tab\",\n\tcopy: \"tui.input.copy\",\n\tselectUp: \"tui.select.up\",\n\tselectDown: \"tui.select.down\",\n\tselectPageUp: \"tui.select.pageUp\",\n\tselectPageDown: \"tui.select.pageDown\",\n\tselectConfirm: \"tui.select.confirm\",\n\tselectCancel: \"tui.select.cancel\",\n\tinterrupt: \"app.interrupt\",\n\tclear: \"app.clear\",\n\texit: \"app.exit\",\n\tsuspend: \"app.suspend\",\n\tcycleThinkingLevel: \"app.thinking.cycle\",\n\tcycleModelForward: \"app.model.cycleForward\",\n\tcycleModelBackward: \"app.model.cycleBackward\",\n\tselectModel: \"app.model.select\",\n\texpandTools: \"app.tools.expand\",\n\ttoggleThinking: \"app.thinking.toggle\",\n\ttoggleSessionNamedFilter: \"app.session.toggleNamedFilter\",\n\texternalEditor: \"app.editor.external\",\n\tfollowUp: \"app.message.followUp\",\n\tdequeue: \"app.message.dequeue\",\n\tpasteImage: \"app.clipboard.pasteImage\",\n\tnewSession: \"app.session.new\",\n\ttree: \"app.session.tree\",\n\tfork: \"app.session.fork\",\n\tresume: \"app.session.resume\",\n\ttreeFoldOrUp: \"app.tree.foldOrUp\",\n\ttreeUnfoldOrDown: \"app.tree.unfoldOrDown\",\n\ttreeEditLabel: \"app.tree.editLabel\",\n\ttreeToggleLabelTimestamp: \"app.tree.toggleLabelTimestamp\",\n\ttoggleSessionPath: \"app.session.togglePath\",\n\ttoggleSessionSort: \"app.session.toggleSort\",\n\trenameSession: \"app.session.rename\",\n\tdeleteSession: \"app.session.delete\",\n\tdeleteSessionNoninvasive: \"app.session.deleteNoninvasive\",\n} as const satisfies Record<string, Keybinding>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {\n\treturn key in KEYBINDING_NAME_MIGRATIONS;\n}\n\nfunction toKeybindingsConfig(value: unknown): KeybindingsConfig {\n\tif (!isRecord(value)) return {};\n\n\tconst config: KeybindingsConfig = {};\n\tfor (const [key, binding] of Object.entries(value)) {\n\t\tif (typeof binding === \"string\") {\n\t\t\tconfig[key] = binding as KeyId;\n\t\t\tcontinue;\n\t\t}\n\t\tif (Array.isArray(binding) && binding.every((entry) => typeof entry === \"string\")) {\n\t\t\tconfig[key] = binding as KeyId[];\n\t\t}\n\t}\n\treturn config;\n}\n\nexport function migrateKeybindingsConfig(rawConfig: Record<string, unknown>): {\n\tconfig: Record<string, unknown>;\n\tmigrated: boolean;\n} {\n\tconst config: Record<string, unknown> = {};\n\tlet migrated = false;\n\n\tfor (const [key, value] of Object.entries(rawConfig)) {\n\t\tconst nextKey = isLegacyKeybindingName(key) ? KEYBINDING_NAME_MIGRATIONS[key] : key;\n\t\tif (nextKey !== key) {\n\t\t\tmigrated = true;\n\t\t}\n\t\tif (key !== nextKey && Object.hasOwn(rawConfig, nextKey)) {\n\t\t\tmigrated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[nextKey] = value;\n\t}\n\n\treturn { config: orderKeybindingsConfig(config), migrated };\n}\n\nfunction orderKeybindingsConfig(config: Record<string, unknown>): Record<string, unknown> {\n\tconst ordered: Record<string, unknown> = {};\n\tfor (const keybinding of Object.keys(KEYBINDINGS)) {\n\t\tif (Object.hasOwn(config, keybinding)) {\n\t\t\tordered[keybinding] = config[keybinding];\n\t\t}\n\t}\n\n\tconst extras = Object.keys(config)\n\t\t.filter((key) => !Object.hasOwn(ordered, key))\n\t\t.sort();\n\tfor (const key of extras) {\n\t\tordered[key] = config[key];\n\t}\n\n\treturn ordered;\n}\n\nfunction loadRawConfig(path: string): Record<string, unknown> | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n\t\treturn isRecord(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class KeybindingsManager extends TuiKeybindingsManager {\n\tprivate configPath: string | undefined;\n\n\tconstructor(userBindings: KeybindingsConfig = {}, configPath?: string) {\n\t\tsuper(KEYBINDINGS, userBindings);\n\t\tthis.configPath = configPath;\n\t}\n\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\n\t\tconst userBindings = KeybindingsManager.loadFromFile(configPath);\n\t\treturn new KeybindingsManager(userBindings, configPath);\n\t}\n\n\treload(): void {\n\t\tif (!this.configPath) return;\n\t\tthis.setUserBindings(KeybindingsManager.loadFromFile(this.configPath));\n\t}\n\n\tgetEffectiveConfig(): KeybindingsConfig {\n\t\treturn this.getResolvedBindings();\n\t}\n\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\n\t\tconst rawConfig = loadRawConfig(path);\n\t\tif (!rawConfig) return {};\n\t\treturn toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);\n\t}\n}\n\nexport type { KeyId, KeybindingsConfig };\n"]}
|
|
1
|
+
{"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Keybinding,\n\ttype KeybindingDefinitions,\n\ttype KeybindingsConfig,\n\ttype KeyId,\n\tTUI_KEYBINDINGS,\n\tKeybindingsManager as TuiKeybindingsManager,\n} from \"@kolisachint/hoocode-tui\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\n\ninterface AppKeybindings {\n\t\"app.interrupt\": true;\n\t\"app.clear\": true;\n\t\"app.exit\": true;\n\t\"app.suspend\": true;\n\t\"app.thinking.cycle\": true;\n\t\"app.model.cycleForward\": true;\n\t\"app.model.cycleBackward\": true;\n\t\"app.model.select\": true;\n\t\"app.tools.expand\": true;\n\t\"app.view.cycleForward\": true;\n\t\"app.view.cycleBackward\": true;\n\t\"app.thinking.toggle\": true;\n\t\"app.tasks.cycleView\": true;\n\t\"app.team.focus\": true;\n\t\"app.team.nudge\": true;\n\t\"app.team.attach\": true;\n\t\"app.session.toggleNamedFilter\": true;\n\t\"app.editor.external\": true;\n\t\"app.message.followUp\": true;\n\t\"app.message.dequeue\": true;\n\t\"app.clipboard.pasteImage\": true;\n\t\"app.input.voiceTranscribe\": true;\n\t\"app.session.new\": true;\n\t\"app.session.tree\": true;\n\t\"app.session.fork\": true;\n\t\"app.session.resume\": true;\n\t\"app.session.changeDirectory\": true;\n\t\"app.session.color.cycleForward\": true;\n\t\"app.session.color.cycleBackward\": true;\n\t\"app.settings.open\": true;\n\t\"app.hotkeys.open\": true;\n\t\"app.mode.cycle\": true;\n\t\"app.tree.foldOrUp\": true;\n\t\"app.tree.unfoldOrDown\": true;\n\t\"app.tree.editLabel\": true;\n\t\"app.tree.toggleLabelTimestamp\": true;\n\t\"app.session.togglePath\": true;\n\t\"app.session.toggleSort\": true;\n\t\"app.session.rename\": true;\n\t\"app.session.delete\": true;\n\t\"app.session.deleteNoninvasive\": true;\n\t\"app.models.save\": true;\n\t\"app.models.enableAll\": true;\n\t\"app.models.clearAll\": true;\n\t\"app.models.toggleProvider\": true;\n\t\"app.models.reorderUp\": true;\n\t\"app.models.reorderDown\": true;\n\t\"app.tree.filter.default\": true;\n\t\"app.tree.filter.noTools\": true;\n\t\"app.tree.filter.userOnly\": true;\n\t\"app.tree.filter.labeledOnly\": true;\n\t\"app.tree.filter.all\": true;\n\t\"app.tree.filter.cycleForward\": true;\n\t\"app.tree.filter.cycleBackward\": true;\n}\n\nexport type AppKeybinding = keyof AppKeybindings;\n\ndeclare module \"@kolisachint/hoocode-tui\" {\n\tinterface Keybindings extends AppKeybindings {}\n}\n\n/**\n * The cockpit layout.\n *\n * Three rings, and which ring a key belongs to is decided by its modifier:\n *\n * - **ctrl — the view.** What is on screen right now: expand, thinking blocks,\n * task panel, model cycling. Pressed many times a minute, so they sit under\n * the hand and never require a second modifier.\n * - **alt — the cockpit.** What the agent *is* and where it works: model,\n * mode, working directory, settings, sessions. Pressed a few times a session.\n * - **overlays.** Inside a picker, the query line is a text field, so every\n * `ctrl+<letter>` there belongs to the *text* (ctrl+a start of line, ctrl+u\n * kill line, ctrl+w kill word). A picker's own verbs are therefore all on\n * `alt+<letter>`, mnemonic to that picker; the picker captures keys while it\n * is open, so reusing a global letter there is unambiguous.\n *\n * Two rules keep the set learnable: shift reverses whatever the unshifted key\n * does, and no binding takes a key the editor or the terminal already owns\n * (ctrl+a/e/b/f/k/u/w/y/d/l/r/g, ctrl+s XOFF, ctrl+m == enter, ctrl+i == tab).\n *\n * Two constraints from the key parser shape which alt keys are usable at all,\n * and `test/keybinding-layout.test.ts` holds both:\n *\n * - Only `alt+<letter>` and `alt+<digit>` survive a terminal without the Kitty\n * keyboard protocol. `alt+[` and `alt+]` arrive as the CSI and OSC\n * introducers and are not parsed as keys; nor is any shift-modified key, so a\n * `shift+…` default is a Kitty-only convenience on top of an unshifted key\n * that works everywhere (as `shift+ctrl+p` has always been).\n * - Legacy `alt+p` and `alt+n` are also accepted as `alt+up` and `alt+down`\n * (the emacs previous/next aliases), so no scope may bind both halves of\n * either pair.\n */\nexport const KEYBINDINGS = {\n\t...TUI_KEYBINDINGS,\n\t\"app.interrupt\": { defaultKeys: \"escape\", description: \"Cancel or abort\" },\n\t\"app.clear\": { defaultKeys: \"ctrl+c\", description: \"Clear editor\" },\n\t\"app.exit\": { defaultKeys: \"ctrl+d\", description: \"Exit when editor is empty\" },\n\t\"app.suspend\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? [] : \"ctrl+z\",\n\t\tdescription: \"Suspend to background\",\n\t},\n\t\"app.thinking.cycle\": {\n\t\tdefaultKeys: \"shift+tab\",\n\t\tdescription: \"Cycle thinking level\",\n\t},\n\t\"app.model.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Cycle to next model\",\n\t},\n\t\"app.model.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+p\",\n\t\tdescription: \"Cycle to previous model\",\n\t},\n\t// alt+m, not ctrl+l: ctrl+l is \"clear the screen\" in every shell and every\n\t// full-screen terminal app, and users press it reflexively to tidy up. It\n\t// opening a model dialog is the single most surprising key in the old set.\n\t\"app.model.select\": { defaultKeys: \"alt+m\", description: \"Open model selector\" },\n\t\"app.tools.expand\": {\n\t\tdefaultKeys: \"ctrl+o\",\n\t\tdescription: \"Jump to the full view from wherever you are, and back again\",\n\t},\n\t// The view dial pairs with ctrl+o on purpose: same letter, different ring.\n\t// alt+o walks the dial a stop at a time and saves where it lands; ctrl+o\n\t// jumps to the far end and back without moving your home stop. One value\n\t// between them, so there is no second \"expanded\" state to keep in sync.\n\t\"app.view.cycleForward\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Cycle tool output view (radar → peek → full)\",\n\t},\n\t\"app.view.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+o\",\n\t\tdescription: \"Cycle tool output view backward\",\n\t},\n\t\"app.thinking.toggle\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Toggle thinking blocks\",\n\t},\n\t\"app.tasks.cycleView\": {\n\t\t// ctrl+n is free in the main editor (no emacs next-line binding here).\n\t\tdefaultKeys: \"ctrl+n\",\n\t\tdescription: \"Cycle task panel view (tasks → subagents → teams, skips empty lenses)\",\n\t},\n\t\"app.team.focus\": {\n\t\t// Pairs with ctrl+n (cycle task panel view): alt+n steps INTO the teams\n\t\t// lens and focuses the role roster (--team only). Not shift+ctrl+n —\n\t\t// Windows Terminal intercepts that as its \"new window\" shortcut, the\n\t\t// same trap that moved app.tasks.cycleView off ctrl+shift+t.\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Focus the team roster (navigate roles, n nudge, a attach)\",\n\t},\n\t\"app.team.nudge\": {\n\t\t// Plain letters are safe here: these fire only while the task panel holds\n\t\t// focus (team-focus mode), never while typing in the editor.\n\t\tdefaultKeys: \"n\",\n\t\tdescription: \"Nudge the selected team role (team focus mode)\",\n\t},\n\t\"app.team.attach\": {\n\t\tdefaultKeys: \"a\",\n\t\tdescription: \"Attach to the selected team role (team focus mode)\",\n\t},\n\t// alt+e, not ctrl+g: ctrl+g is emacs/readline \"abort\" — the key you hit to\n\t// get out of something. Having it launch $EDITOR inverts that reflex.\n\t\"app.editor.external\": {\n\t\tdefaultKeys: \"alt+e\",\n\t\tdescription: \"Open external editor\",\n\t},\n\t\"app.message.followUp\": {\n\t\tdefaultKeys: \"alt+enter\",\n\t\tdescription: \"Queue follow-up message\",\n\t},\n\t\"app.message.dequeue\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Restore queued messages\",\n\t},\n\t\"app.clipboard.pasteImage\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? \"alt+v\" : \"ctrl+v\",\n\t\tdescription: \"Paste image from clipboard\",\n\t},\n\t// alt+r, not ctrl+r: ctrl+r is reverse history search in every shell, and it\n\t// was also the session picker's rename key — one chord, two meanings.\n\t\"app.input.voiceTranscribe\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Record voice and transcribe into the editor\",\n\t},\n\t// The two destructive-ish session moves stay unbound by default. /new\n\t// replaces the transcript and /fork needs a message picked out of it, so\n\t// neither wants to be one stray chord away; both remain bindable by hand.\n\t\"app.session.new\": { defaultKeys: [], description: \"Start a new session\" },\n\t\"app.session.fork\": { defaultKeys: [], description: \"Fork current session\" },\n\t// Navigation is non-destructive, so it gets keys: t for tree, h for history.\n\t\"app.session.tree\": { defaultKeys: \"alt+t\", description: \"Open session tree\" },\n\t\"app.session.resume\": { defaultKeys: \"alt+h\", description: \"Resume a session from history\" },\n\t\"app.session.changeDirectory\": {\n\t\tdefaultKeys: \"alt+w\",\n\t\tdescription: \"Change working directory (move to another repo without quitting)\",\n\t},\n\t// alt+c (\"colour\"), and the tree's filter cycle has the same letter on\n\t// purpose: the tree captures keys while it is open, so the two are never live\n\t// at once, and both mean \"step to the next one\" wherever you press them. The\n\t// backward half needs Kitty, like every other shift-modified default here.\n\t\"app.session.color.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Cycle the session chip's color\",\n\t},\n\t\"app.session.color.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Cycle the session chip's color backward\",\n\t},\n\t\"app.settings.open\": { defaultKeys: \"alt+s\", description: \"Open settings\" },\n\t\"app.hotkeys.open\": { defaultKeys: \"alt+k\", description: \"Show keyboard shortcuts\" },\n\t\"app.mode.cycle\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Cycle agent mode (ask → plan → build → debug)\",\n\t},\n\t\"app.tree.foldOrUp\": {\n\t\tdefaultKeys: [\"ctrl+left\", \"alt+left\"],\n\t\tdescription: \"Fold tree branch or move up\",\n\t},\n\t\"app.tree.unfoldOrDown\": {\n\t\tdefaultKeys: [\"ctrl+right\", \"alt+right\"],\n\t\tdescription: \"Unfold tree branch or move down\",\n\t},\n\t\"app.tree.editLabel\": {\n\t\tdefaultKeys: \"shift+l\",\n\t\tdescription: \"Edit tree label\",\n\t},\n\t\"app.tree.toggleLabelTimestamp\": {\n\t\tdefaultKeys: \"shift+t\",\n\t\tdescription: \"Toggle tree label timestamps\",\n\t},\n\t// Session picker verbs. All on alt so the picker's query line keeps the\n\t// emacs editing keys it used to lose: ctrl+a jumped to the start of the\n\t// query *and* enabled every model, ctrl+d deleted a character *and* deleted\n\t// the highlighted session.\n\t\"app.session.togglePath\": {\n\t\tdefaultKeys: \"alt+p\",\n\t\tdescription: \"Toggle session path display\",\n\t},\n\t\"app.session.toggleSort\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Toggle session sort order\",\n\t},\n\t\"app.session.rename\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Rename session\",\n\t},\n\t\"app.session.toggleNamedFilter\": {\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Toggle named session filter\",\n\t},\n\t\"app.session.delete\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Delete session\",\n\t},\n\t\"app.session.deleteNoninvasive\": {\n\t\tdefaultKeys: \"ctrl+backspace\",\n\t\tdescription: \"Delete session when query is empty\",\n\t},\n\t// Model picker verbs, same rule. ctrl+s in particular was XOFF: on a terminal\n\t// with flow control still on, \"save\" froze the session instead.\n\t\"app.models.save\": {\n\t\tdefaultKeys: \"alt+s\",\n\t\tdescription: \"Save model selection\",\n\t},\n\t\"app.models.enableAll\": {\n\t\tdefaultKeys: \"alt+a\",\n\t\tdescription: \"Enable all models\",\n\t},\n\t\"app.models.clearAll\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Clear all models\",\n\t},\n\t// alt+g (\"group\"), not alt+p: on a terminal without the Kitty protocol, alt+p\n\t// arrives as ESC-p, which the key parser also accepts as alt+up — and alt+up\n\t// is this same picker's reorder key.\n\t\"app.models.toggleProvider\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Toggle all models for provider\",\n\t},\n\t\"app.models.reorderUp\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Move model up in order\",\n\t},\n\t\"app.models.reorderDown\": {\n\t\tdefaultKeys: \"alt+down\",\n\t\tdescription: \"Move model down in order\",\n\t},\n\t\"app.options.next\": { defaultKeys: \"right\", description: \"Confirm and advance to the next question\" },\n\t\"app.options.back\": { defaultKeys: \"left\", description: \"Go back to the previous question\" },\n\t// Five lenses in a fixed order, so they are numbered rather than lettered:\n\t// alt+1..alt+5 needs no mnemonic and collides with nothing. The old set\n\t// (ctrl+d/t/u/l/a) collided with delete-char, thinking, kill-to-start,\n\t// clear-screen and start-of-line respectively.\n\t\"app.tree.filter.default\": {\n\t\tdefaultKeys: \"alt+1\",\n\t\tdescription: \"Tree filter: default view\",\n\t},\n\t\"app.tree.filter.noTools\": {\n\t\tdefaultKeys: \"alt+2\",\n\t\tdescription: \"Tree filter: hide tool results\",\n\t},\n\t\"app.tree.filter.userOnly\": {\n\t\tdefaultKeys: \"alt+3\",\n\t\tdescription: \"Tree filter: user messages only\",\n\t},\n\t\"app.tree.filter.labeledOnly\": {\n\t\tdefaultKeys: \"alt+4\",\n\t\tdescription: \"Tree filter: labeled entries only\",\n\t},\n\t\"app.tree.filter.all\": {\n\t\tdefaultKeys: \"alt+5\",\n\t\tdescription: \"Tree filter: show all entries\",\n\t},\n\t// alt+c for \"cycle\". Not a bracket pair, tempting as `alt+[` / `alt+]` are:\n\t// without the Kitty protocol those arrive as ESC-[ and ESC-], which are the\n\t// CSI and OSC introducers and so are not parsed as keys at all. The backward\n\t// half needs Kitty, like every other shift-modified default here.\n\t\"app.tree.filter.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Tree filter: cycle forward\",\n\t},\n\t\"app.tree.filter.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Tree filter: cycle backward\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nconst KEYBINDING_NAME_MIGRATIONS = {\n\tcursorUp: \"tui.editor.cursorUp\",\n\tcursorDown: \"tui.editor.cursorDown\",\n\tcursorLeft: \"tui.editor.cursorLeft\",\n\tcursorRight: \"tui.editor.cursorRight\",\n\tcursorWordLeft: \"tui.editor.cursorWordLeft\",\n\tcursorWordRight: \"tui.editor.cursorWordRight\",\n\tcursorLineStart: \"tui.editor.cursorLineStart\",\n\tcursorLineEnd: \"tui.editor.cursorLineEnd\",\n\tjumpForward: \"tui.editor.jumpForward\",\n\tjumpBackward: \"tui.editor.jumpBackward\",\n\tpageUp: \"tui.editor.pageUp\",\n\tpageDown: \"tui.editor.pageDown\",\n\tdeleteCharBackward: \"tui.editor.deleteCharBackward\",\n\tdeleteCharForward: \"tui.editor.deleteCharForward\",\n\tdeleteWordBackward: \"tui.editor.deleteWordBackward\",\n\tdeleteWordForward: \"tui.editor.deleteWordForward\",\n\tdeleteToLineStart: \"tui.editor.deleteToLineStart\",\n\tdeleteToLineEnd: \"tui.editor.deleteToLineEnd\",\n\tyank: \"tui.editor.yank\",\n\tyankPop: \"tui.editor.yankPop\",\n\tundo: \"tui.editor.undo\",\n\tnewLine: \"tui.input.newLine\",\n\tsubmit: \"tui.input.submit\",\n\ttab: \"tui.input.tab\",\n\tcopy: \"tui.input.copy\",\n\tselectUp: \"tui.select.up\",\n\tselectDown: \"tui.select.down\",\n\tselectPageUp: \"tui.select.pageUp\",\n\tselectPageDown: \"tui.select.pageDown\",\n\tselectConfirm: \"tui.select.confirm\",\n\tselectCancel: \"tui.select.cancel\",\n\tinterrupt: \"app.interrupt\",\n\tclear: \"app.clear\",\n\texit: \"app.exit\",\n\tsuspend: \"app.suspend\",\n\tcycleThinkingLevel: \"app.thinking.cycle\",\n\tcycleModelForward: \"app.model.cycleForward\",\n\tcycleModelBackward: \"app.model.cycleBackward\",\n\tselectModel: \"app.model.select\",\n\texpandTools: \"app.tools.expand\",\n\ttoggleThinking: \"app.thinking.toggle\",\n\ttoggleSessionNamedFilter: \"app.session.toggleNamedFilter\",\n\texternalEditor: \"app.editor.external\",\n\tfollowUp: \"app.message.followUp\",\n\tdequeue: \"app.message.dequeue\",\n\tpasteImage: \"app.clipboard.pasteImage\",\n\tnewSession: \"app.session.new\",\n\ttree: \"app.session.tree\",\n\tfork: \"app.session.fork\",\n\tresume: \"app.session.resume\",\n\ttreeFoldOrUp: \"app.tree.foldOrUp\",\n\ttreeUnfoldOrDown: \"app.tree.unfoldOrDown\",\n\ttreeEditLabel: \"app.tree.editLabel\",\n\ttreeToggleLabelTimestamp: \"app.tree.toggleLabelTimestamp\",\n\ttoggleSessionPath: \"app.session.togglePath\",\n\ttoggleSessionSort: \"app.session.toggleSort\",\n\trenameSession: \"app.session.rename\",\n\tdeleteSession: \"app.session.delete\",\n\tdeleteSessionNoninvasive: \"app.session.deleteNoninvasive\",\n} as const satisfies Record<string, Keybinding>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {\n\treturn key in KEYBINDING_NAME_MIGRATIONS;\n}\n\nfunction toKeybindingsConfig(value: unknown): KeybindingsConfig {\n\tif (!isRecord(value)) return {};\n\n\tconst config: KeybindingsConfig = {};\n\tfor (const [key, binding] of Object.entries(value)) {\n\t\tif (typeof binding === \"string\") {\n\t\t\tconfig[key] = binding as KeyId;\n\t\t\tcontinue;\n\t\t}\n\t\tif (Array.isArray(binding) && binding.every((entry) => typeof entry === \"string\")) {\n\t\t\tconfig[key] = binding as KeyId[];\n\t\t}\n\t}\n\treturn config;\n}\n\nexport function migrateKeybindingsConfig(rawConfig: Record<string, unknown>): {\n\tconfig: Record<string, unknown>;\n\tmigrated: boolean;\n} {\n\tconst config: Record<string, unknown> = {};\n\tlet migrated = false;\n\n\tfor (const [key, value] of Object.entries(rawConfig)) {\n\t\tconst nextKey = isLegacyKeybindingName(key) ? KEYBINDING_NAME_MIGRATIONS[key] : key;\n\t\tif (nextKey !== key) {\n\t\t\tmigrated = true;\n\t\t}\n\t\tif (key !== nextKey && Object.hasOwn(rawConfig, nextKey)) {\n\t\t\tmigrated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[nextKey] = value;\n\t}\n\n\treturn { config: orderKeybindingsConfig(config), migrated };\n}\n\nfunction orderKeybindingsConfig(config: Record<string, unknown>): Record<string, unknown> {\n\tconst ordered: Record<string, unknown> = {};\n\tfor (const keybinding of Object.keys(KEYBINDINGS)) {\n\t\tif (Object.hasOwn(config, keybinding)) {\n\t\t\tordered[keybinding] = config[keybinding];\n\t\t}\n\t}\n\n\tconst extras = Object.keys(config)\n\t\t.filter((key) => !Object.hasOwn(ordered, key))\n\t\t.sort();\n\tfor (const key of extras) {\n\t\tordered[key] = config[key];\n\t}\n\n\treturn ordered;\n}\n\nfunction loadRawConfig(path: string): Record<string, unknown> | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n\t\treturn isRecord(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class KeybindingsManager extends TuiKeybindingsManager {\n\tprivate configPath: string | undefined;\n\n\tconstructor(userBindings: KeybindingsConfig = {}, configPath?: string) {\n\t\tsuper(KEYBINDINGS, userBindings);\n\t\tthis.configPath = configPath;\n\t}\n\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\n\t\tconst userBindings = KeybindingsManager.loadFromFile(configPath);\n\t\treturn new KeybindingsManager(userBindings, configPath);\n\t}\n\n\treload(): void {\n\t\tif (!this.configPath) return;\n\t\tthis.setUserBindings(KeybindingsManager.loadFromFile(this.configPath));\n\t}\n\n\tgetEffectiveConfig(): KeybindingsConfig {\n\t\treturn this.getResolvedBindings();\n\t}\n\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\n\t\tconst rawConfig = loadRawConfig(path);\n\t\tif (!rawConfig) return {};\n\t\treturn toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);\n\t}\n}\n\nexport type { KeyId, KeybindingsConfig };\n"]}
|
package/dist/core/keybindings.js
CHANGED
|
@@ -61,31 +61,20 @@ export const KEYBINDINGS = {
|
|
|
61
61
|
"app.model.select": { defaultKeys: "alt+m", description: "Open model selector" },
|
|
62
62
|
"app.tools.expand": {
|
|
63
63
|
defaultKeys: "ctrl+o",
|
|
64
|
-
description: "
|
|
64
|
+
description: "Jump to the full view from wherever you are, and back again",
|
|
65
65
|
},
|
|
66
66
|
// The view dial pairs with ctrl+o on purpose: same letter, different ring.
|
|
67
|
-
//
|
|
67
|
+
// alt+o walks the dial a stop at a time and saves where it lands; ctrl+o
|
|
68
|
+
// jumps to the far end and back without moving your home stop. One value
|
|
69
|
+
// between them, so there is no second "expanded" state to keep in sync.
|
|
68
70
|
"app.view.cycleForward": {
|
|
69
71
|
defaultKeys: "alt+o",
|
|
70
|
-
description: "Cycle tool output view (radar →
|
|
72
|
+
description: "Cycle tool output view (radar → peek → full)",
|
|
71
73
|
},
|
|
72
74
|
"app.view.cycleBackward": {
|
|
73
75
|
defaultKeys: "shift+alt+o",
|
|
74
76
|
description: "Cycle tool output view backward",
|
|
75
77
|
},
|
|
76
|
-
// The one-at-a-time counterpart to ctrl+o's all-or-nothing. The transcript is
|
|
77
|
-
// bottom-anchored with no app-level scrolling — anything far enough up is in
|
|
78
|
-
// the terminal's own scrollback, which this process cannot address — so "open
|
|
79
|
-
// one" can only ever mean "open one at the tail". Repeating the key peels
|
|
80
|
-
// backwards from there.
|
|
81
|
-
"app.tools.unfoldOne": {
|
|
82
|
-
defaultKeys: "alt+u",
|
|
83
|
-
description: "Open the newest folded thing — a chain in radar, a tool body otherwise",
|
|
84
|
-
},
|
|
85
|
-
"app.tools.foldOne": {
|
|
86
|
-
defaultKeys: "shift+alt+u",
|
|
87
|
-
description: "Re-fold the most recently opened chain or tool block",
|
|
88
|
-
},
|
|
89
78
|
"app.thinking.toggle": {
|
|
90
79
|
defaultKeys: "ctrl+t",
|
|
91
80
|
description: "Toggle thinking blocks",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Keybinding,\n\ttype KeybindingDefinitions,\n\ttype KeybindingsConfig,\n\ttype KeyId,\n\tTUI_KEYBINDINGS,\n\tKeybindingsManager as TuiKeybindingsManager,\n} from \"@kolisachint/hoocode-tui\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\n\ninterface AppKeybindings {\n\t\"app.interrupt\": true;\n\t\"app.clear\": true;\n\t\"app.exit\": true;\n\t\"app.suspend\": true;\n\t\"app.thinking.cycle\": true;\n\t\"app.model.cycleForward\": true;\n\t\"app.model.cycleBackward\": true;\n\t\"app.model.select\": true;\n\t\"app.tools.expand\": true;\n\t\"app.view.cycleForward\": true;\n\t\"app.view.cycleBackward\": true;\n\t\"app.tools.unfoldOne\": true;\n\t\"app.tools.foldOne\": true;\n\t\"app.thinking.toggle\": true;\n\t\"app.tasks.cycleView\": true;\n\t\"app.team.focus\": true;\n\t\"app.team.nudge\": true;\n\t\"app.team.attach\": true;\n\t\"app.session.toggleNamedFilter\": true;\n\t\"app.editor.external\": true;\n\t\"app.message.followUp\": true;\n\t\"app.message.dequeue\": true;\n\t\"app.clipboard.pasteImage\": true;\n\t\"app.input.voiceTranscribe\": true;\n\t\"app.session.new\": true;\n\t\"app.session.tree\": true;\n\t\"app.session.fork\": true;\n\t\"app.session.resume\": true;\n\t\"app.session.changeDirectory\": true;\n\t\"app.session.color.cycleForward\": true;\n\t\"app.session.color.cycleBackward\": true;\n\t\"app.settings.open\": true;\n\t\"app.hotkeys.open\": true;\n\t\"app.mode.cycle\": true;\n\t\"app.tree.foldOrUp\": true;\n\t\"app.tree.unfoldOrDown\": true;\n\t\"app.tree.editLabel\": true;\n\t\"app.tree.toggleLabelTimestamp\": true;\n\t\"app.session.togglePath\": true;\n\t\"app.session.toggleSort\": true;\n\t\"app.session.rename\": true;\n\t\"app.session.delete\": true;\n\t\"app.session.deleteNoninvasive\": true;\n\t\"app.models.save\": true;\n\t\"app.models.enableAll\": true;\n\t\"app.models.clearAll\": true;\n\t\"app.models.toggleProvider\": true;\n\t\"app.models.reorderUp\": true;\n\t\"app.models.reorderDown\": true;\n\t\"app.tree.filter.default\": true;\n\t\"app.tree.filter.noTools\": true;\n\t\"app.tree.filter.userOnly\": true;\n\t\"app.tree.filter.labeledOnly\": true;\n\t\"app.tree.filter.all\": true;\n\t\"app.tree.filter.cycleForward\": true;\n\t\"app.tree.filter.cycleBackward\": true;\n}\n\nexport type AppKeybinding = keyof AppKeybindings;\n\ndeclare module \"@kolisachint/hoocode-tui\" {\n\tinterface Keybindings extends AppKeybindings {}\n}\n\n/**\n * The cockpit layout.\n *\n * Three rings, and which ring a key belongs to is decided by its modifier:\n *\n * - **ctrl — the view.** What is on screen right now: expand, thinking blocks,\n * task panel, model cycling. Pressed many times a minute, so they sit under\n * the hand and never require a second modifier.\n * - **alt — the cockpit.** What the agent *is* and where it works: model,\n * mode, working directory, settings, sessions. Pressed a few times a session.\n * - **overlays.** Inside a picker, the query line is a text field, so every\n * `ctrl+<letter>` there belongs to the *text* (ctrl+a start of line, ctrl+u\n * kill line, ctrl+w kill word). A picker's own verbs are therefore all on\n * `alt+<letter>`, mnemonic to that picker; the picker captures keys while it\n * is open, so reusing a global letter there is unambiguous.\n *\n * Two rules keep the set learnable: shift reverses whatever the unshifted key\n * does, and no binding takes a key the editor or the terminal already owns\n * (ctrl+a/e/b/f/k/u/w/y/d/l/r/g, ctrl+s XOFF, ctrl+m == enter, ctrl+i == tab).\n *\n * Two constraints from the key parser shape which alt keys are usable at all,\n * and `test/keybinding-layout.test.ts` holds both:\n *\n * - Only `alt+<letter>` and `alt+<digit>` survive a terminal without the Kitty\n * keyboard protocol. `alt+[` and `alt+]` arrive as the CSI and OSC\n * introducers and are not parsed as keys; nor is any shift-modified key, so a\n * `shift+…` default is a Kitty-only convenience on top of an unshifted key\n * that works everywhere (as `shift+ctrl+p` has always been).\n * - Legacy `alt+p` and `alt+n` are also accepted as `alt+up` and `alt+down`\n * (the emacs previous/next aliases), so no scope may bind both halves of\n * either pair.\n */\nexport const KEYBINDINGS = {\n\t...TUI_KEYBINDINGS,\n\t\"app.interrupt\": { defaultKeys: \"escape\", description: \"Cancel or abort\" },\n\t\"app.clear\": { defaultKeys: \"ctrl+c\", description: \"Clear editor\" },\n\t\"app.exit\": { defaultKeys: \"ctrl+d\", description: \"Exit when editor is empty\" },\n\t\"app.suspend\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? [] : \"ctrl+z\",\n\t\tdescription: \"Suspend to background\",\n\t},\n\t\"app.thinking.cycle\": {\n\t\tdefaultKeys: \"shift+tab\",\n\t\tdescription: \"Cycle thinking level\",\n\t},\n\t\"app.model.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Cycle to next model\",\n\t},\n\t\"app.model.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+p\",\n\t\tdescription: \"Cycle to previous model\",\n\t},\n\t// alt+m, not ctrl+l: ctrl+l is \"clear the screen\" in every shell and every\n\t// full-screen terminal app, and users press it reflexively to tidy up. It\n\t// opening a model dialog is the single most surprising key in the old set.\n\t\"app.model.select\": { defaultKeys: \"alt+m\", description: \"Open model selector\" },\n\t\"app.tools.expand\": {\n\t\tdefaultKeys: \"ctrl+o\",\n\t\tdescription: \"Expand or collapse what is in front of you (tool bodies, header, summaries)\",\n\t},\n\t// The view dial pairs with ctrl+o on purpose: same letter, different ring.\n\t// ctrl+o opens what is already there; alt+o decides how much is ever there.\n\t\"app.view.cycleForward\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Cycle tool output view (radar → glance → full)\",\n\t},\n\t\"app.view.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+o\",\n\t\tdescription: \"Cycle tool output view backward\",\n\t},\n\t// The one-at-a-time counterpart to ctrl+o's all-or-nothing. The transcript is\n\t// bottom-anchored with no app-level scrolling — anything far enough up is in\n\t// the terminal's own scrollback, which this process cannot address — so \"open\n\t// one\" can only ever mean \"open one at the tail\". Repeating the key peels\n\t// backwards from there.\n\t\"app.tools.unfoldOne\": {\n\t\tdefaultKeys: \"alt+u\",\n\t\tdescription: \"Open the newest folded thing — a chain in radar, a tool body otherwise\",\n\t},\n\t\"app.tools.foldOne\": {\n\t\tdefaultKeys: \"shift+alt+u\",\n\t\tdescription: \"Re-fold the most recently opened chain or tool block\",\n\t},\n\t\"app.thinking.toggle\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Toggle thinking blocks\",\n\t},\n\t\"app.tasks.cycleView\": {\n\t\t// ctrl+n is free in the main editor (no emacs next-line binding here).\n\t\tdefaultKeys: \"ctrl+n\",\n\t\tdescription: \"Cycle task panel view (tasks → subagents → teams, skips empty lenses)\",\n\t},\n\t\"app.team.focus\": {\n\t\t// Pairs with ctrl+n (cycle task panel view): alt+n steps INTO the teams\n\t\t// lens and focuses the role roster (--team only). Not shift+ctrl+n —\n\t\t// Windows Terminal intercepts that as its \"new window\" shortcut, the\n\t\t// same trap that moved app.tasks.cycleView off ctrl+shift+t.\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Focus the team roster (navigate roles, n nudge, a attach)\",\n\t},\n\t\"app.team.nudge\": {\n\t\t// Plain letters are safe here: these fire only while the task panel holds\n\t\t// focus (team-focus mode), never while typing in the editor.\n\t\tdefaultKeys: \"n\",\n\t\tdescription: \"Nudge the selected team role (team focus mode)\",\n\t},\n\t\"app.team.attach\": {\n\t\tdefaultKeys: \"a\",\n\t\tdescription: \"Attach to the selected team role (team focus mode)\",\n\t},\n\t// alt+e, not ctrl+g: ctrl+g is emacs/readline \"abort\" — the key you hit to\n\t// get out of something. Having it launch $EDITOR inverts that reflex.\n\t\"app.editor.external\": {\n\t\tdefaultKeys: \"alt+e\",\n\t\tdescription: \"Open external editor\",\n\t},\n\t\"app.message.followUp\": {\n\t\tdefaultKeys: \"alt+enter\",\n\t\tdescription: \"Queue follow-up message\",\n\t},\n\t\"app.message.dequeue\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Restore queued messages\",\n\t},\n\t\"app.clipboard.pasteImage\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? \"alt+v\" : \"ctrl+v\",\n\t\tdescription: \"Paste image from clipboard\",\n\t},\n\t// alt+r, not ctrl+r: ctrl+r is reverse history search in every shell, and it\n\t// was also the session picker's rename key — one chord, two meanings.\n\t\"app.input.voiceTranscribe\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Record voice and transcribe into the editor\",\n\t},\n\t// The two destructive-ish session moves stay unbound by default. /new\n\t// replaces the transcript and /fork needs a message picked out of it, so\n\t// neither wants to be one stray chord away; both remain bindable by hand.\n\t\"app.session.new\": { defaultKeys: [], description: \"Start a new session\" },\n\t\"app.session.fork\": { defaultKeys: [], description: \"Fork current session\" },\n\t// Navigation is non-destructive, so it gets keys: t for tree, h for history.\n\t\"app.session.tree\": { defaultKeys: \"alt+t\", description: \"Open session tree\" },\n\t\"app.session.resume\": { defaultKeys: \"alt+h\", description: \"Resume a session from history\" },\n\t\"app.session.changeDirectory\": {\n\t\tdefaultKeys: \"alt+w\",\n\t\tdescription: \"Change working directory (move to another repo without quitting)\",\n\t},\n\t// alt+c (\"colour\"), and the tree's filter cycle has the same letter on\n\t// purpose: the tree captures keys while it is open, so the two are never live\n\t// at once, and both mean \"step to the next one\" wherever you press them. The\n\t// backward half needs Kitty, like every other shift-modified default here.\n\t\"app.session.color.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Cycle the session chip's color\",\n\t},\n\t\"app.session.color.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Cycle the session chip's color backward\",\n\t},\n\t\"app.settings.open\": { defaultKeys: \"alt+s\", description: \"Open settings\" },\n\t\"app.hotkeys.open\": { defaultKeys: \"alt+k\", description: \"Show keyboard shortcuts\" },\n\t\"app.mode.cycle\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Cycle agent mode (ask → plan → build → debug)\",\n\t},\n\t\"app.tree.foldOrUp\": {\n\t\tdefaultKeys: [\"ctrl+left\", \"alt+left\"],\n\t\tdescription: \"Fold tree branch or move up\",\n\t},\n\t\"app.tree.unfoldOrDown\": {\n\t\tdefaultKeys: [\"ctrl+right\", \"alt+right\"],\n\t\tdescription: \"Unfold tree branch or move down\",\n\t},\n\t\"app.tree.editLabel\": {\n\t\tdefaultKeys: \"shift+l\",\n\t\tdescription: \"Edit tree label\",\n\t},\n\t\"app.tree.toggleLabelTimestamp\": {\n\t\tdefaultKeys: \"shift+t\",\n\t\tdescription: \"Toggle tree label timestamps\",\n\t},\n\t// Session picker verbs. All on alt so the picker's query line keeps the\n\t// emacs editing keys it used to lose: ctrl+a jumped to the start of the\n\t// query *and* enabled every model, ctrl+d deleted a character *and* deleted\n\t// the highlighted session.\n\t\"app.session.togglePath\": {\n\t\tdefaultKeys: \"alt+p\",\n\t\tdescription: \"Toggle session path display\",\n\t},\n\t\"app.session.toggleSort\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Toggle session sort order\",\n\t},\n\t\"app.session.rename\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Rename session\",\n\t},\n\t\"app.session.toggleNamedFilter\": {\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Toggle named session filter\",\n\t},\n\t\"app.session.delete\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Delete session\",\n\t},\n\t\"app.session.deleteNoninvasive\": {\n\t\tdefaultKeys: \"ctrl+backspace\",\n\t\tdescription: \"Delete session when query is empty\",\n\t},\n\t// Model picker verbs, same rule. ctrl+s in particular was XOFF: on a terminal\n\t// with flow control still on, \"save\" froze the session instead.\n\t\"app.models.save\": {\n\t\tdefaultKeys: \"alt+s\",\n\t\tdescription: \"Save model selection\",\n\t},\n\t\"app.models.enableAll\": {\n\t\tdefaultKeys: \"alt+a\",\n\t\tdescription: \"Enable all models\",\n\t},\n\t\"app.models.clearAll\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Clear all models\",\n\t},\n\t// alt+g (\"group\"), not alt+p: on a terminal without the Kitty protocol, alt+p\n\t// arrives as ESC-p, which the key parser also accepts as alt+up — and alt+up\n\t// is this same picker's reorder key.\n\t\"app.models.toggleProvider\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Toggle all models for provider\",\n\t},\n\t\"app.models.reorderUp\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Move model up in order\",\n\t},\n\t\"app.models.reorderDown\": {\n\t\tdefaultKeys: \"alt+down\",\n\t\tdescription: \"Move model down in order\",\n\t},\n\t\"app.options.next\": { defaultKeys: \"right\", description: \"Confirm and advance to the next question\" },\n\t\"app.options.back\": { defaultKeys: \"left\", description: \"Go back to the previous question\" },\n\t// Five lenses in a fixed order, so they are numbered rather than lettered:\n\t// alt+1..alt+5 needs no mnemonic and collides with nothing. The old set\n\t// (ctrl+d/t/u/l/a) collided with delete-char, thinking, kill-to-start,\n\t// clear-screen and start-of-line respectively.\n\t\"app.tree.filter.default\": {\n\t\tdefaultKeys: \"alt+1\",\n\t\tdescription: \"Tree filter: default view\",\n\t},\n\t\"app.tree.filter.noTools\": {\n\t\tdefaultKeys: \"alt+2\",\n\t\tdescription: \"Tree filter: hide tool results\",\n\t},\n\t\"app.tree.filter.userOnly\": {\n\t\tdefaultKeys: \"alt+3\",\n\t\tdescription: \"Tree filter: user messages only\",\n\t},\n\t\"app.tree.filter.labeledOnly\": {\n\t\tdefaultKeys: \"alt+4\",\n\t\tdescription: \"Tree filter: labeled entries only\",\n\t},\n\t\"app.tree.filter.all\": {\n\t\tdefaultKeys: \"alt+5\",\n\t\tdescription: \"Tree filter: show all entries\",\n\t},\n\t// alt+c for \"cycle\". Not a bracket pair, tempting as `alt+[` / `alt+]` are:\n\t// without the Kitty protocol those arrive as ESC-[ and ESC-], which are the\n\t// CSI and OSC introducers and so are not parsed as keys at all. The backward\n\t// half needs Kitty, like every other shift-modified default here.\n\t\"app.tree.filter.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Tree filter: cycle forward\",\n\t},\n\t\"app.tree.filter.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Tree filter: cycle backward\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nconst KEYBINDING_NAME_MIGRATIONS = {\n\tcursorUp: \"tui.editor.cursorUp\",\n\tcursorDown: \"tui.editor.cursorDown\",\n\tcursorLeft: \"tui.editor.cursorLeft\",\n\tcursorRight: \"tui.editor.cursorRight\",\n\tcursorWordLeft: \"tui.editor.cursorWordLeft\",\n\tcursorWordRight: \"tui.editor.cursorWordRight\",\n\tcursorLineStart: \"tui.editor.cursorLineStart\",\n\tcursorLineEnd: \"tui.editor.cursorLineEnd\",\n\tjumpForward: \"tui.editor.jumpForward\",\n\tjumpBackward: \"tui.editor.jumpBackward\",\n\tpageUp: \"tui.editor.pageUp\",\n\tpageDown: \"tui.editor.pageDown\",\n\tdeleteCharBackward: \"tui.editor.deleteCharBackward\",\n\tdeleteCharForward: \"tui.editor.deleteCharForward\",\n\tdeleteWordBackward: \"tui.editor.deleteWordBackward\",\n\tdeleteWordForward: \"tui.editor.deleteWordForward\",\n\tdeleteToLineStart: \"tui.editor.deleteToLineStart\",\n\tdeleteToLineEnd: \"tui.editor.deleteToLineEnd\",\n\tyank: \"tui.editor.yank\",\n\tyankPop: \"tui.editor.yankPop\",\n\tundo: \"tui.editor.undo\",\n\tnewLine: \"tui.input.newLine\",\n\tsubmit: \"tui.input.submit\",\n\ttab: \"tui.input.tab\",\n\tcopy: \"tui.input.copy\",\n\tselectUp: \"tui.select.up\",\n\tselectDown: \"tui.select.down\",\n\tselectPageUp: \"tui.select.pageUp\",\n\tselectPageDown: \"tui.select.pageDown\",\n\tselectConfirm: \"tui.select.confirm\",\n\tselectCancel: \"tui.select.cancel\",\n\tinterrupt: \"app.interrupt\",\n\tclear: \"app.clear\",\n\texit: \"app.exit\",\n\tsuspend: \"app.suspend\",\n\tcycleThinkingLevel: \"app.thinking.cycle\",\n\tcycleModelForward: \"app.model.cycleForward\",\n\tcycleModelBackward: \"app.model.cycleBackward\",\n\tselectModel: \"app.model.select\",\n\texpandTools: \"app.tools.expand\",\n\ttoggleThinking: \"app.thinking.toggle\",\n\ttoggleSessionNamedFilter: \"app.session.toggleNamedFilter\",\n\texternalEditor: \"app.editor.external\",\n\tfollowUp: \"app.message.followUp\",\n\tdequeue: \"app.message.dequeue\",\n\tpasteImage: \"app.clipboard.pasteImage\",\n\tnewSession: \"app.session.new\",\n\ttree: \"app.session.tree\",\n\tfork: \"app.session.fork\",\n\tresume: \"app.session.resume\",\n\ttreeFoldOrUp: \"app.tree.foldOrUp\",\n\ttreeUnfoldOrDown: \"app.tree.unfoldOrDown\",\n\ttreeEditLabel: \"app.tree.editLabel\",\n\ttreeToggleLabelTimestamp: \"app.tree.toggleLabelTimestamp\",\n\ttoggleSessionPath: \"app.session.togglePath\",\n\ttoggleSessionSort: \"app.session.toggleSort\",\n\trenameSession: \"app.session.rename\",\n\tdeleteSession: \"app.session.delete\",\n\tdeleteSessionNoninvasive: \"app.session.deleteNoninvasive\",\n} as const satisfies Record<string, Keybinding>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {\n\treturn key in KEYBINDING_NAME_MIGRATIONS;\n}\n\nfunction toKeybindingsConfig(value: unknown): KeybindingsConfig {\n\tif (!isRecord(value)) return {};\n\n\tconst config: KeybindingsConfig = {};\n\tfor (const [key, binding] of Object.entries(value)) {\n\t\tif (typeof binding === \"string\") {\n\t\t\tconfig[key] = binding as KeyId;\n\t\t\tcontinue;\n\t\t}\n\t\tif (Array.isArray(binding) && binding.every((entry) => typeof entry === \"string\")) {\n\t\t\tconfig[key] = binding as KeyId[];\n\t\t}\n\t}\n\treturn config;\n}\n\nexport function migrateKeybindingsConfig(rawConfig: Record<string, unknown>): {\n\tconfig: Record<string, unknown>;\n\tmigrated: boolean;\n} {\n\tconst config: Record<string, unknown> = {};\n\tlet migrated = false;\n\n\tfor (const [key, value] of Object.entries(rawConfig)) {\n\t\tconst nextKey = isLegacyKeybindingName(key) ? KEYBINDING_NAME_MIGRATIONS[key] : key;\n\t\tif (nextKey !== key) {\n\t\t\tmigrated = true;\n\t\t}\n\t\tif (key !== nextKey && Object.hasOwn(rawConfig, nextKey)) {\n\t\t\tmigrated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[nextKey] = value;\n\t}\n\n\treturn { config: orderKeybindingsConfig(config), migrated };\n}\n\nfunction orderKeybindingsConfig(config: Record<string, unknown>): Record<string, unknown> {\n\tconst ordered: Record<string, unknown> = {};\n\tfor (const keybinding of Object.keys(KEYBINDINGS)) {\n\t\tif (Object.hasOwn(config, keybinding)) {\n\t\t\tordered[keybinding] = config[keybinding];\n\t\t}\n\t}\n\n\tconst extras = Object.keys(config)\n\t\t.filter((key) => !Object.hasOwn(ordered, key))\n\t\t.sort();\n\tfor (const key of extras) {\n\t\tordered[key] = config[key];\n\t}\n\n\treturn ordered;\n}\n\nfunction loadRawConfig(path: string): Record<string, unknown> | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n\t\treturn isRecord(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class KeybindingsManager extends TuiKeybindingsManager {\n\tprivate configPath: string | undefined;\n\n\tconstructor(userBindings: KeybindingsConfig = {}, configPath?: string) {\n\t\tsuper(KEYBINDINGS, userBindings);\n\t\tthis.configPath = configPath;\n\t}\n\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\n\t\tconst userBindings = KeybindingsManager.loadFromFile(configPath);\n\t\treturn new KeybindingsManager(userBindings, configPath);\n\t}\n\n\treload(): void {\n\t\tif (!this.configPath) return;\n\t\tthis.setUserBindings(KeybindingsManager.loadFromFile(this.configPath));\n\t}\n\n\tgetEffectiveConfig(): KeybindingsConfig {\n\t\treturn this.getResolvedBindings();\n\t}\n\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\n\t\tconst rawConfig = loadRawConfig(path);\n\t\tif (!rawConfig) return {};\n\t\treturn toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);\n\t}\n}\n\nexport type { KeyId, KeybindingsConfig };\n"]}
|
|
1
|
+
{"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Keybinding,\n\ttype KeybindingDefinitions,\n\ttype KeybindingsConfig,\n\ttype KeyId,\n\tTUI_KEYBINDINGS,\n\tKeybindingsManager as TuiKeybindingsManager,\n} from \"@kolisachint/hoocode-tui\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\n\ninterface AppKeybindings {\n\t\"app.interrupt\": true;\n\t\"app.clear\": true;\n\t\"app.exit\": true;\n\t\"app.suspend\": true;\n\t\"app.thinking.cycle\": true;\n\t\"app.model.cycleForward\": true;\n\t\"app.model.cycleBackward\": true;\n\t\"app.model.select\": true;\n\t\"app.tools.expand\": true;\n\t\"app.view.cycleForward\": true;\n\t\"app.view.cycleBackward\": true;\n\t\"app.thinking.toggle\": true;\n\t\"app.tasks.cycleView\": true;\n\t\"app.team.focus\": true;\n\t\"app.team.nudge\": true;\n\t\"app.team.attach\": true;\n\t\"app.session.toggleNamedFilter\": true;\n\t\"app.editor.external\": true;\n\t\"app.message.followUp\": true;\n\t\"app.message.dequeue\": true;\n\t\"app.clipboard.pasteImage\": true;\n\t\"app.input.voiceTranscribe\": true;\n\t\"app.session.new\": true;\n\t\"app.session.tree\": true;\n\t\"app.session.fork\": true;\n\t\"app.session.resume\": true;\n\t\"app.session.changeDirectory\": true;\n\t\"app.session.color.cycleForward\": true;\n\t\"app.session.color.cycleBackward\": true;\n\t\"app.settings.open\": true;\n\t\"app.hotkeys.open\": true;\n\t\"app.mode.cycle\": true;\n\t\"app.tree.foldOrUp\": true;\n\t\"app.tree.unfoldOrDown\": true;\n\t\"app.tree.editLabel\": true;\n\t\"app.tree.toggleLabelTimestamp\": true;\n\t\"app.session.togglePath\": true;\n\t\"app.session.toggleSort\": true;\n\t\"app.session.rename\": true;\n\t\"app.session.delete\": true;\n\t\"app.session.deleteNoninvasive\": true;\n\t\"app.models.save\": true;\n\t\"app.models.enableAll\": true;\n\t\"app.models.clearAll\": true;\n\t\"app.models.toggleProvider\": true;\n\t\"app.models.reorderUp\": true;\n\t\"app.models.reorderDown\": true;\n\t\"app.tree.filter.default\": true;\n\t\"app.tree.filter.noTools\": true;\n\t\"app.tree.filter.userOnly\": true;\n\t\"app.tree.filter.labeledOnly\": true;\n\t\"app.tree.filter.all\": true;\n\t\"app.tree.filter.cycleForward\": true;\n\t\"app.tree.filter.cycleBackward\": true;\n}\n\nexport type AppKeybinding = keyof AppKeybindings;\n\ndeclare module \"@kolisachint/hoocode-tui\" {\n\tinterface Keybindings extends AppKeybindings {}\n}\n\n/**\n * The cockpit layout.\n *\n * Three rings, and which ring a key belongs to is decided by its modifier:\n *\n * - **ctrl — the view.** What is on screen right now: expand, thinking blocks,\n * task panel, model cycling. Pressed many times a minute, so they sit under\n * the hand and never require a second modifier.\n * - **alt — the cockpit.** What the agent *is* and where it works: model,\n * mode, working directory, settings, sessions. Pressed a few times a session.\n * - **overlays.** Inside a picker, the query line is a text field, so every\n * `ctrl+<letter>` there belongs to the *text* (ctrl+a start of line, ctrl+u\n * kill line, ctrl+w kill word). A picker's own verbs are therefore all on\n * `alt+<letter>`, mnemonic to that picker; the picker captures keys while it\n * is open, so reusing a global letter there is unambiguous.\n *\n * Two rules keep the set learnable: shift reverses whatever the unshifted key\n * does, and no binding takes a key the editor or the terminal already owns\n * (ctrl+a/e/b/f/k/u/w/y/d/l/r/g, ctrl+s XOFF, ctrl+m == enter, ctrl+i == tab).\n *\n * Two constraints from the key parser shape which alt keys are usable at all,\n * and `test/keybinding-layout.test.ts` holds both:\n *\n * - Only `alt+<letter>` and `alt+<digit>` survive a terminal without the Kitty\n * keyboard protocol. `alt+[` and `alt+]` arrive as the CSI and OSC\n * introducers and are not parsed as keys; nor is any shift-modified key, so a\n * `shift+…` default is a Kitty-only convenience on top of an unshifted key\n * that works everywhere (as `shift+ctrl+p` has always been).\n * - Legacy `alt+p` and `alt+n` are also accepted as `alt+up` and `alt+down`\n * (the emacs previous/next aliases), so no scope may bind both halves of\n * either pair.\n */\nexport const KEYBINDINGS = {\n\t...TUI_KEYBINDINGS,\n\t\"app.interrupt\": { defaultKeys: \"escape\", description: \"Cancel or abort\" },\n\t\"app.clear\": { defaultKeys: \"ctrl+c\", description: \"Clear editor\" },\n\t\"app.exit\": { defaultKeys: \"ctrl+d\", description: \"Exit when editor is empty\" },\n\t\"app.suspend\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? [] : \"ctrl+z\",\n\t\tdescription: \"Suspend to background\",\n\t},\n\t\"app.thinking.cycle\": {\n\t\tdefaultKeys: \"shift+tab\",\n\t\tdescription: \"Cycle thinking level\",\n\t},\n\t\"app.model.cycleForward\": {\n\t\tdefaultKeys: \"ctrl+p\",\n\t\tdescription: \"Cycle to next model\",\n\t},\n\t\"app.model.cycleBackward\": {\n\t\tdefaultKeys: \"shift+ctrl+p\",\n\t\tdescription: \"Cycle to previous model\",\n\t},\n\t// alt+m, not ctrl+l: ctrl+l is \"clear the screen\" in every shell and every\n\t// full-screen terminal app, and users press it reflexively to tidy up. It\n\t// opening a model dialog is the single most surprising key in the old set.\n\t\"app.model.select\": { defaultKeys: \"alt+m\", description: \"Open model selector\" },\n\t\"app.tools.expand\": {\n\t\tdefaultKeys: \"ctrl+o\",\n\t\tdescription: \"Jump to the full view from wherever you are, and back again\",\n\t},\n\t// The view dial pairs with ctrl+o on purpose: same letter, different ring.\n\t// alt+o walks the dial a stop at a time and saves where it lands; ctrl+o\n\t// jumps to the far end and back without moving your home stop. One value\n\t// between them, so there is no second \"expanded\" state to keep in sync.\n\t\"app.view.cycleForward\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Cycle tool output view (radar → peek → full)\",\n\t},\n\t\"app.view.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+o\",\n\t\tdescription: \"Cycle tool output view backward\",\n\t},\n\t\"app.thinking.toggle\": {\n\t\tdefaultKeys: \"ctrl+t\",\n\t\tdescription: \"Toggle thinking blocks\",\n\t},\n\t\"app.tasks.cycleView\": {\n\t\t// ctrl+n is free in the main editor (no emacs next-line binding here).\n\t\tdefaultKeys: \"ctrl+n\",\n\t\tdescription: \"Cycle task panel view (tasks → subagents → teams, skips empty lenses)\",\n\t},\n\t\"app.team.focus\": {\n\t\t// Pairs with ctrl+n (cycle task panel view): alt+n steps INTO the teams\n\t\t// lens and focuses the role roster (--team only). Not shift+ctrl+n —\n\t\t// Windows Terminal intercepts that as its \"new window\" shortcut, the\n\t\t// same trap that moved app.tasks.cycleView off ctrl+shift+t.\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Focus the team roster (navigate roles, n nudge, a attach)\",\n\t},\n\t\"app.team.nudge\": {\n\t\t// Plain letters are safe here: these fire only while the task panel holds\n\t\t// focus (team-focus mode), never while typing in the editor.\n\t\tdefaultKeys: \"n\",\n\t\tdescription: \"Nudge the selected team role (team focus mode)\",\n\t},\n\t\"app.team.attach\": {\n\t\tdefaultKeys: \"a\",\n\t\tdescription: \"Attach to the selected team role (team focus mode)\",\n\t},\n\t// alt+e, not ctrl+g: ctrl+g is emacs/readline \"abort\" — the key you hit to\n\t// get out of something. Having it launch $EDITOR inverts that reflex.\n\t\"app.editor.external\": {\n\t\tdefaultKeys: \"alt+e\",\n\t\tdescription: \"Open external editor\",\n\t},\n\t\"app.message.followUp\": {\n\t\tdefaultKeys: \"alt+enter\",\n\t\tdescription: \"Queue follow-up message\",\n\t},\n\t\"app.message.dequeue\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Restore queued messages\",\n\t},\n\t\"app.clipboard.pasteImage\": {\n\t\tdefaultKeys: process.platform === \"win32\" ? \"alt+v\" : \"ctrl+v\",\n\t\tdescription: \"Paste image from clipboard\",\n\t},\n\t// alt+r, not ctrl+r: ctrl+r is reverse history search in every shell, and it\n\t// was also the session picker's rename key — one chord, two meanings.\n\t\"app.input.voiceTranscribe\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Record voice and transcribe into the editor\",\n\t},\n\t// The two destructive-ish session moves stay unbound by default. /new\n\t// replaces the transcript and /fork needs a message picked out of it, so\n\t// neither wants to be one stray chord away; both remain bindable by hand.\n\t\"app.session.new\": { defaultKeys: [], description: \"Start a new session\" },\n\t\"app.session.fork\": { defaultKeys: [], description: \"Fork current session\" },\n\t// Navigation is non-destructive, so it gets keys: t for tree, h for history.\n\t\"app.session.tree\": { defaultKeys: \"alt+t\", description: \"Open session tree\" },\n\t\"app.session.resume\": { defaultKeys: \"alt+h\", description: \"Resume a session from history\" },\n\t\"app.session.changeDirectory\": {\n\t\tdefaultKeys: \"alt+w\",\n\t\tdescription: \"Change working directory (move to another repo without quitting)\",\n\t},\n\t// alt+c (\"colour\"), and the tree's filter cycle has the same letter on\n\t// purpose: the tree captures keys while it is open, so the two are never live\n\t// at once, and both mean \"step to the next one\" wherever you press them. The\n\t// backward half needs Kitty, like every other shift-modified default here.\n\t\"app.session.color.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Cycle the session chip's color\",\n\t},\n\t\"app.session.color.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Cycle the session chip's color backward\",\n\t},\n\t\"app.settings.open\": { defaultKeys: \"alt+s\", description: \"Open settings\" },\n\t\"app.hotkeys.open\": { defaultKeys: \"alt+k\", description: \"Show keyboard shortcuts\" },\n\t\"app.mode.cycle\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Cycle agent mode (ask → plan → build → debug)\",\n\t},\n\t\"app.tree.foldOrUp\": {\n\t\tdefaultKeys: [\"ctrl+left\", \"alt+left\"],\n\t\tdescription: \"Fold tree branch or move up\",\n\t},\n\t\"app.tree.unfoldOrDown\": {\n\t\tdefaultKeys: [\"ctrl+right\", \"alt+right\"],\n\t\tdescription: \"Unfold tree branch or move down\",\n\t},\n\t\"app.tree.editLabel\": {\n\t\tdefaultKeys: \"shift+l\",\n\t\tdescription: \"Edit tree label\",\n\t},\n\t\"app.tree.toggleLabelTimestamp\": {\n\t\tdefaultKeys: \"shift+t\",\n\t\tdescription: \"Toggle tree label timestamps\",\n\t},\n\t// Session picker verbs. All on alt so the picker's query line keeps the\n\t// emacs editing keys it used to lose: ctrl+a jumped to the start of the\n\t// query *and* enabled every model, ctrl+d deleted a character *and* deleted\n\t// the highlighted session.\n\t\"app.session.togglePath\": {\n\t\tdefaultKeys: \"alt+p\",\n\t\tdescription: \"Toggle session path display\",\n\t},\n\t\"app.session.toggleSort\": {\n\t\tdefaultKeys: \"alt+o\",\n\t\tdescription: \"Toggle session sort order\",\n\t},\n\t\"app.session.rename\": {\n\t\tdefaultKeys: \"alt+r\",\n\t\tdescription: \"Rename session\",\n\t},\n\t\"app.session.toggleNamedFilter\": {\n\t\tdefaultKeys: \"alt+n\",\n\t\tdescription: \"Toggle named session filter\",\n\t},\n\t\"app.session.delete\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Delete session\",\n\t},\n\t\"app.session.deleteNoninvasive\": {\n\t\tdefaultKeys: \"ctrl+backspace\",\n\t\tdescription: \"Delete session when query is empty\",\n\t},\n\t// Model picker verbs, same rule. ctrl+s in particular was XOFF: on a terminal\n\t// with flow control still on, \"save\" froze the session instead.\n\t\"app.models.save\": {\n\t\tdefaultKeys: \"alt+s\",\n\t\tdescription: \"Save model selection\",\n\t},\n\t\"app.models.enableAll\": {\n\t\tdefaultKeys: \"alt+a\",\n\t\tdescription: \"Enable all models\",\n\t},\n\t\"app.models.clearAll\": {\n\t\tdefaultKeys: \"alt+x\",\n\t\tdescription: \"Clear all models\",\n\t},\n\t// alt+g (\"group\"), not alt+p: on a terminal without the Kitty protocol, alt+p\n\t// arrives as ESC-p, which the key parser also accepts as alt+up — and alt+up\n\t// is this same picker's reorder key.\n\t\"app.models.toggleProvider\": {\n\t\tdefaultKeys: \"alt+g\",\n\t\tdescription: \"Toggle all models for provider\",\n\t},\n\t\"app.models.reorderUp\": {\n\t\tdefaultKeys: \"alt+up\",\n\t\tdescription: \"Move model up in order\",\n\t},\n\t\"app.models.reorderDown\": {\n\t\tdefaultKeys: \"alt+down\",\n\t\tdescription: \"Move model down in order\",\n\t},\n\t\"app.options.next\": { defaultKeys: \"right\", description: \"Confirm and advance to the next question\" },\n\t\"app.options.back\": { defaultKeys: \"left\", description: \"Go back to the previous question\" },\n\t// Five lenses in a fixed order, so they are numbered rather than lettered:\n\t// alt+1..alt+5 needs no mnemonic and collides with nothing. The old set\n\t// (ctrl+d/t/u/l/a) collided with delete-char, thinking, kill-to-start,\n\t// clear-screen and start-of-line respectively.\n\t\"app.tree.filter.default\": {\n\t\tdefaultKeys: \"alt+1\",\n\t\tdescription: \"Tree filter: default view\",\n\t},\n\t\"app.tree.filter.noTools\": {\n\t\tdefaultKeys: \"alt+2\",\n\t\tdescription: \"Tree filter: hide tool results\",\n\t},\n\t\"app.tree.filter.userOnly\": {\n\t\tdefaultKeys: \"alt+3\",\n\t\tdescription: \"Tree filter: user messages only\",\n\t},\n\t\"app.tree.filter.labeledOnly\": {\n\t\tdefaultKeys: \"alt+4\",\n\t\tdescription: \"Tree filter: labeled entries only\",\n\t},\n\t\"app.tree.filter.all\": {\n\t\tdefaultKeys: \"alt+5\",\n\t\tdescription: \"Tree filter: show all entries\",\n\t},\n\t// alt+c for \"cycle\". Not a bracket pair, tempting as `alt+[` / `alt+]` are:\n\t// without the Kitty protocol those arrive as ESC-[ and ESC-], which are the\n\t// CSI and OSC introducers and so are not parsed as keys at all. The backward\n\t// half needs Kitty, like every other shift-modified default here.\n\t\"app.tree.filter.cycleForward\": {\n\t\tdefaultKeys: \"alt+c\",\n\t\tdescription: \"Tree filter: cycle forward\",\n\t},\n\t\"app.tree.filter.cycleBackward\": {\n\t\tdefaultKeys: \"shift+alt+c\",\n\t\tdescription: \"Tree filter: cycle backward\",\n\t},\n} as const satisfies KeybindingDefinitions;\n\nconst KEYBINDING_NAME_MIGRATIONS = {\n\tcursorUp: \"tui.editor.cursorUp\",\n\tcursorDown: \"tui.editor.cursorDown\",\n\tcursorLeft: \"tui.editor.cursorLeft\",\n\tcursorRight: \"tui.editor.cursorRight\",\n\tcursorWordLeft: \"tui.editor.cursorWordLeft\",\n\tcursorWordRight: \"tui.editor.cursorWordRight\",\n\tcursorLineStart: \"tui.editor.cursorLineStart\",\n\tcursorLineEnd: \"tui.editor.cursorLineEnd\",\n\tjumpForward: \"tui.editor.jumpForward\",\n\tjumpBackward: \"tui.editor.jumpBackward\",\n\tpageUp: \"tui.editor.pageUp\",\n\tpageDown: \"tui.editor.pageDown\",\n\tdeleteCharBackward: \"tui.editor.deleteCharBackward\",\n\tdeleteCharForward: \"tui.editor.deleteCharForward\",\n\tdeleteWordBackward: \"tui.editor.deleteWordBackward\",\n\tdeleteWordForward: \"tui.editor.deleteWordForward\",\n\tdeleteToLineStart: \"tui.editor.deleteToLineStart\",\n\tdeleteToLineEnd: \"tui.editor.deleteToLineEnd\",\n\tyank: \"tui.editor.yank\",\n\tyankPop: \"tui.editor.yankPop\",\n\tundo: \"tui.editor.undo\",\n\tnewLine: \"tui.input.newLine\",\n\tsubmit: \"tui.input.submit\",\n\ttab: \"tui.input.tab\",\n\tcopy: \"tui.input.copy\",\n\tselectUp: \"tui.select.up\",\n\tselectDown: \"tui.select.down\",\n\tselectPageUp: \"tui.select.pageUp\",\n\tselectPageDown: \"tui.select.pageDown\",\n\tselectConfirm: \"tui.select.confirm\",\n\tselectCancel: \"tui.select.cancel\",\n\tinterrupt: \"app.interrupt\",\n\tclear: \"app.clear\",\n\texit: \"app.exit\",\n\tsuspend: \"app.suspend\",\n\tcycleThinkingLevel: \"app.thinking.cycle\",\n\tcycleModelForward: \"app.model.cycleForward\",\n\tcycleModelBackward: \"app.model.cycleBackward\",\n\tselectModel: \"app.model.select\",\n\texpandTools: \"app.tools.expand\",\n\ttoggleThinking: \"app.thinking.toggle\",\n\ttoggleSessionNamedFilter: \"app.session.toggleNamedFilter\",\n\texternalEditor: \"app.editor.external\",\n\tfollowUp: \"app.message.followUp\",\n\tdequeue: \"app.message.dequeue\",\n\tpasteImage: \"app.clipboard.pasteImage\",\n\tnewSession: \"app.session.new\",\n\ttree: \"app.session.tree\",\n\tfork: \"app.session.fork\",\n\tresume: \"app.session.resume\",\n\ttreeFoldOrUp: \"app.tree.foldOrUp\",\n\ttreeUnfoldOrDown: \"app.tree.unfoldOrDown\",\n\ttreeEditLabel: \"app.tree.editLabel\",\n\ttreeToggleLabelTimestamp: \"app.tree.toggleLabelTimestamp\",\n\ttoggleSessionPath: \"app.session.togglePath\",\n\ttoggleSessionSort: \"app.session.toggleSort\",\n\trenameSession: \"app.session.rename\",\n\tdeleteSession: \"app.session.delete\",\n\tdeleteSessionNoninvasive: \"app.session.deleteNoninvasive\",\n} as const satisfies Record<string, Keybinding>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isLegacyKeybindingName(key: string): key is keyof typeof KEYBINDING_NAME_MIGRATIONS {\n\treturn key in KEYBINDING_NAME_MIGRATIONS;\n}\n\nfunction toKeybindingsConfig(value: unknown): KeybindingsConfig {\n\tif (!isRecord(value)) return {};\n\n\tconst config: KeybindingsConfig = {};\n\tfor (const [key, binding] of Object.entries(value)) {\n\t\tif (typeof binding === \"string\") {\n\t\t\tconfig[key] = binding as KeyId;\n\t\t\tcontinue;\n\t\t}\n\t\tif (Array.isArray(binding) && binding.every((entry) => typeof entry === \"string\")) {\n\t\t\tconfig[key] = binding as KeyId[];\n\t\t}\n\t}\n\treturn config;\n}\n\nexport function migrateKeybindingsConfig(rawConfig: Record<string, unknown>): {\n\tconfig: Record<string, unknown>;\n\tmigrated: boolean;\n} {\n\tconst config: Record<string, unknown> = {};\n\tlet migrated = false;\n\n\tfor (const [key, value] of Object.entries(rawConfig)) {\n\t\tconst nextKey = isLegacyKeybindingName(key) ? KEYBINDING_NAME_MIGRATIONS[key] : key;\n\t\tif (nextKey !== key) {\n\t\t\tmigrated = true;\n\t\t}\n\t\tif (key !== nextKey && Object.hasOwn(rawConfig, nextKey)) {\n\t\t\tmigrated = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconfig[nextKey] = value;\n\t}\n\n\treturn { config: orderKeybindingsConfig(config), migrated };\n}\n\nfunction orderKeybindingsConfig(config: Record<string, unknown>): Record<string, unknown> {\n\tconst ordered: Record<string, unknown> = {};\n\tfor (const keybinding of Object.keys(KEYBINDINGS)) {\n\t\tif (Object.hasOwn(config, keybinding)) {\n\t\t\tordered[keybinding] = config[keybinding];\n\t\t}\n\t}\n\n\tconst extras = Object.keys(config)\n\t\t.filter((key) => !Object.hasOwn(ordered, key))\n\t\t.sort();\n\tfor (const key of extras) {\n\t\tordered[key] = config[key];\n\t}\n\n\treturn ordered;\n}\n\nfunction loadRawConfig(path: string): Record<string, unknown> | undefined {\n\tif (!existsSync(path)) return undefined;\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n\t\treturn isRecord(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport class KeybindingsManager extends TuiKeybindingsManager {\n\tprivate configPath: string | undefined;\n\n\tconstructor(userBindings: KeybindingsConfig = {}, configPath?: string) {\n\t\tsuper(KEYBINDINGS, userBindings);\n\t\tthis.configPath = configPath;\n\t}\n\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\n\t\tconst userBindings = KeybindingsManager.loadFromFile(configPath);\n\t\treturn new KeybindingsManager(userBindings, configPath);\n\t}\n\n\treload(): void {\n\t\tif (!this.configPath) return;\n\t\tthis.setUserBindings(KeybindingsManager.loadFromFile(this.configPath));\n\t}\n\n\tgetEffectiveConfig(): KeybindingsConfig {\n\t\treturn this.getResolvedBindings();\n\t}\n\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\n\t\tconst rawConfig = loadRawConfig(path);\n\t\tif (!rawConfig) return {};\n\t\treturn toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config);\n\t}\n}\n\nexport type { KeyId, KeybindingsConfig };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-defaults.d.ts","sourceRoot":"","sources":["../../src/core/settings-defaults.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwFT,CAAC","sourcesContent":["import type { Settings } from \"./settings-manager.js\";\n\nexport const DEFAULT_SETTINGS = {\n\ttransport: \"auto\",\n\tsteeringMode: \"one-at-a-time\",\n\tfollowUpMode: \"one-at-a-time\",\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t\tmaxContextRatio: 0.75,\n\t},\n\ttoolOutput: {\n\t\tmaxBytes: 32 * 1024,\n\t\tmaxLines: 800,\n\t},\n\tcontextGc: {\n\t\tenabled: true,\n\t},\n\tvoice: {\n\t\tsilenceMs: 800,\n\t},\n\twebtools: {\n\t\ttimeoutSecs: 15,\n\t},\n\tdisabledTools: [],\n\ttoolOutputView: \"
|
|
1
|
+
{"version":3,"file":"settings-defaults.d.ts","sourceRoot":"","sources":["../../src/core/settings-defaults.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwFT,CAAC","sourcesContent":["import type { Settings } from \"./settings-manager.js\";\n\nexport const DEFAULT_SETTINGS = {\n\ttransport: \"auto\",\n\tsteeringMode: \"one-at-a-time\",\n\tfollowUpMode: \"one-at-a-time\",\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t\tmaxContextRatio: 0.75,\n\t},\n\ttoolOutput: {\n\t\tmaxBytes: 32 * 1024,\n\t\tmaxLines: 800,\n\t},\n\tcontextGc: {\n\t\tenabled: true,\n\t},\n\tvoice: {\n\t\tsilenceMs: 800,\n\t},\n\twebtools: {\n\t\ttimeoutSecs: 15,\n\t},\n\tdisabledTools: [],\n\ttoolOutputView: \"peek\",\n\tbranchSummary: {\n\t\treserveTokens: 16384,\n\t\tskipPrompt: false,\n\t},\n\tretry: {\n\t\tenabled: true,\n\t\tmaxRetries: 3,\n\t\tbaseDelayMs: 2000,\n\t\tprovider: {\n\t\t\tmaxRetryDelayMs: 60000,\n\t\t},\n\t},\n\thideThinkingBlock: false,\n\tquietStartup: false,\n\tcollapseChangelog: false,\n\tenableInstallTelemetry: true,\n\tenableSkillCommands: true,\n\tenableSubagent: true,\n\twarmSubagents: false,\n\tmaxSubagentDepth: 2,\n\tnestedSubagentConcurrency: 2,\n\tenableTodoWrite: true,\n\tenablePluginTools: false,\n\tpluginInstallScope: \"user\",\n\tdeferMcpSchemas: true,\n\tenableWebTools: false,\n\tenableSemanticIndex: true,\n\tembsearchThresholdBytes: 0,\n\tlearnMaxSessions: 20,\n\tlearnMaxAgeDays: 30,\n\tlearnMinRepeats: 2,\n\tlearnMinRequestRepeats: 3,\n\tlearnMaxProposals: 8,\n\tlight: false,\n\tterminal: {\n\t\tshowImages: true,\n\t\timageWidthCells: 60,\n\t\tclearOnShrink: false,\n\t\tshowTerminalProgress: false,\n\t\tchimeOnTurnComplete: false,\n\t},\n\timages: {\n\t\tautoResize: true,\n\t\tblockImages: false,\n\t},\n\tdoubleEscapeAction: \"tree\",\n\ttreeFilterMode: \"default\",\n\teditorBorder: \"box\",\n\teditorPaddingX: 1,\n\tautocompleteMaxVisible: 5,\n\tmarkdown: {\n\t\tcodeBlockIndent: \" \",\n\t},\n\twarnings: {\n\t\tanthropicExtraUsage: true,\n\t\twebsearchApiKey: true,\n\t},\n\tpackages: [],\n\textensions: [],\n\tskills: [],\n\tprompts: [],\n\tslashCommands: [],\n\tthemes: [],\n} satisfies Settings;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-defaults.js","sourceRoot":"","sources":["../../src/core/settings-defaults.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC/B,SAAS,EAAE,MAAM;IACjB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE;QACX,OAAO,EAAE,IAAI;QACb,aAAa,EAAE,KAAK;QACpB,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,IAAI;KACrB;IACD,UAAU,EAAE;QACX,QAAQ,EAAE,EAAE,GAAG,IAAI;QACnB,QAAQ,EAAE,GAAG;KACb;IACD,SAAS,EAAE;QACV,OAAO,EAAE,IAAI;KACb;IACD,KAAK,EAAE;QACN,SAAS,EAAE,GAAG;KACd;IACD,QAAQ,EAAE;QACT,WAAW,EAAE,EAAE;KACf;IACD,aAAa,EAAE,EAAE;IACjB,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"settings-defaults.js","sourceRoot":"","sources":["../../src/core/settings-defaults.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC/B,SAAS,EAAE,MAAM;IACjB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE;QACX,OAAO,EAAE,IAAI;QACb,aAAa,EAAE,KAAK;QACpB,gBAAgB,EAAE,KAAK;QACvB,eAAe,EAAE,IAAI;KACrB;IACD,UAAU,EAAE;QACX,QAAQ,EAAE,EAAE,GAAG,IAAI;QACnB,QAAQ,EAAE,GAAG;KACb;IACD,SAAS,EAAE;QACV,OAAO,EAAE,IAAI;KACb;IACD,KAAK,EAAE;QACN,SAAS,EAAE,GAAG;KACd;IACD,QAAQ,EAAE;QACT,WAAW,EAAE,EAAE;KACf;IACD,aAAa,EAAE,EAAE;IACjB,cAAc,EAAE,MAAM;IACtB,aAAa,EAAE;QACd,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,KAAK;KACjB;IACD,KAAK,EAAE;QACN,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,CAAC;QACb,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACT,eAAe,EAAE,KAAK;SACtB;KACD;IACD,iBAAiB,EAAE,KAAK;IACxB,YAAY,EAAE,KAAK;IACnB,iBAAiB,EAAE,KAAK;IACxB,sBAAsB,EAAE,IAAI;IAC5B,mBAAmB,EAAE,IAAI;IACzB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,KAAK;IACpB,gBAAgB,EAAE,CAAC;IACnB,yBAAyB,EAAE,CAAC;IAC5B,eAAe,EAAE,IAAI;IACrB,iBAAiB,EAAE,KAAK;IACxB,kBAAkB,EAAE,MAAM;IAC1B,eAAe,EAAE,IAAI;IACrB,cAAc,EAAE,KAAK;IACrB,mBAAmB,EAAE,IAAI;IACzB,uBAAuB,EAAE,CAAC;IAC1B,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,EAAE;IACnB,eAAe,EAAE,CAAC;IAClB,sBAAsB,EAAE,CAAC;IACzB,iBAAiB,EAAE,CAAC;IACpB,KAAK,EAAE,KAAK;IACZ,QAAQ,EAAE;QACT,UAAU,EAAE,IAAI;QAChB,eAAe,EAAE,EAAE;QACnB,aAAa,EAAE,KAAK;QACpB,oBAAoB,EAAE,KAAK;QAC3B,mBAAmB,EAAE,KAAK;KAC1B;IACD,MAAM,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,KAAK;KAClB;IACD,kBAAkB,EAAE,MAAM;IAC1B,cAAc,EAAE,SAAS;IACzB,YAAY,EAAE,KAAK;IACnB,cAAc,EAAE,CAAC;IACjB,sBAAsB,EAAE,CAAC;IACzB,QAAQ,EAAE;QACT,eAAe,EAAE,IAAI;KACrB;IACD,QAAQ,EAAE;QACT,mBAAmB,EAAE,IAAI;QACzB,eAAe,EAAE,IAAI;KACrB;IACD,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,EAAE;IACd,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,EAAE;IACX,aAAa,EAAE,EAAE;IACjB,MAAM,EAAE,EAAE;CACS,CAAC","sourcesContent":["import type { Settings } from \"./settings-manager.js\";\n\nexport const DEFAULT_SETTINGS = {\n\ttransport: \"auto\",\n\tsteeringMode: \"one-at-a-time\",\n\tfollowUpMode: \"one-at-a-time\",\n\tcompaction: {\n\t\tenabled: true,\n\t\treserveTokens: 16384,\n\t\tkeepRecentTokens: 20000,\n\t\tmaxContextRatio: 0.75,\n\t},\n\ttoolOutput: {\n\t\tmaxBytes: 32 * 1024,\n\t\tmaxLines: 800,\n\t},\n\tcontextGc: {\n\t\tenabled: true,\n\t},\n\tvoice: {\n\t\tsilenceMs: 800,\n\t},\n\twebtools: {\n\t\ttimeoutSecs: 15,\n\t},\n\tdisabledTools: [],\n\ttoolOutputView: \"peek\",\n\tbranchSummary: {\n\t\treserveTokens: 16384,\n\t\tskipPrompt: false,\n\t},\n\tretry: {\n\t\tenabled: true,\n\t\tmaxRetries: 3,\n\t\tbaseDelayMs: 2000,\n\t\tprovider: {\n\t\t\tmaxRetryDelayMs: 60000,\n\t\t},\n\t},\n\thideThinkingBlock: false,\n\tquietStartup: false,\n\tcollapseChangelog: false,\n\tenableInstallTelemetry: true,\n\tenableSkillCommands: true,\n\tenableSubagent: true,\n\twarmSubagents: false,\n\tmaxSubagentDepth: 2,\n\tnestedSubagentConcurrency: 2,\n\tenableTodoWrite: true,\n\tenablePluginTools: false,\n\tpluginInstallScope: \"user\",\n\tdeferMcpSchemas: true,\n\tenableWebTools: false,\n\tenableSemanticIndex: true,\n\tembsearchThresholdBytes: 0,\n\tlearnMaxSessions: 20,\n\tlearnMaxAgeDays: 30,\n\tlearnMinRepeats: 2,\n\tlearnMinRequestRepeats: 3,\n\tlearnMaxProposals: 8,\n\tlight: false,\n\tterminal: {\n\t\tshowImages: true,\n\t\timageWidthCells: 60,\n\t\tclearOnShrink: false,\n\t\tshowTerminalProgress: false,\n\t\tchimeOnTurnComplete: false,\n\t},\n\timages: {\n\t\tautoResize: true,\n\t\tblockImages: false,\n\t},\n\tdoubleEscapeAction: \"tree\",\n\ttreeFilterMode: \"default\",\n\teditorBorder: \"box\",\n\teditorPaddingX: 1,\n\tautocompleteMaxVisible: 5,\n\tmarkdown: {\n\t\tcodeBlockIndent: \" \",\n\t},\n\twarnings: {\n\t\tanthropicExtraUsage: true,\n\t\twebsearchApiKey: true,\n\t},\n\tpackages: [],\n\textensions: [],\n\tskills: [],\n\tprompts: [],\n\tslashCommands: [],\n\tthemes: [],\n} satisfies Settings;\n"]}
|
|
@@ -134,7 +134,7 @@ export declare class SettingsManager {
|
|
|
134
134
|
getDisabledTools(): string[];
|
|
135
135
|
setDisabledTools(names: string[]): void;
|
|
136
136
|
/**
|
|
137
|
-
* How much of a tool call the transcript shows (radar /
|
|
137
|
+
* How much of a tool call the transcript shows (radar / peek / full).
|
|
138
138
|
*
|
|
139
139
|
* Settings files written before the dial existed carry the old three-value
|
|
140
140
|
* `toolOutputDisplay` key. They are read here rather than rewritten on load,
|