@codex-infinity/pi-infinity 0.60.2 → 0.61.2

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.
Files changed (248) hide show
  1. package/CHANGELOG.md +59 -1
  2. package/README.md +10 -0
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js +1 -0
  5. package/dist/bun/cli.js.map +1 -1
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/config-selector.js.map +1 -1
  8. package/dist/cli/file-processor.js.map +1 -1
  9. package/dist/cli/initial-message.js.map +1 -1
  10. package/dist/cli/list-models.js.map +1 -1
  11. package/dist/cli/session-picker.d.ts.map +1 -1
  12. package/dist/cli/session-picker.js +2 -1
  13. package/dist/cli/session-picker.js.map +1 -1
  14. package/dist/cli.d.ts.map +1 -1
  15. package/dist/cli.js +1 -0
  16. package/dist/cli.js.map +1 -1
  17. package/dist/config.js.map +1 -1
  18. package/dist/core/agent-session.d.ts.map +1 -1
  19. package/dist/core/agent-session.js +50 -69
  20. package/dist/core/agent-session.js.map +1 -1
  21. package/dist/core/auth-storage.js +4 -8
  22. package/dist/core/auth-storage.js.map +1 -1
  23. package/dist/core/bash-executor.js.map +1 -1
  24. package/dist/core/compaction/branch-summarization.js.map +1 -1
  25. package/dist/core/compaction/compaction.js.map +1 -1
  26. package/dist/core/compaction/utils.js.map +1 -1
  27. package/dist/core/event-bus.js.map +1 -1
  28. package/dist/core/exec.js.map +1 -1
  29. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  30. package/dist/core/export-html/index.js.map +1 -1
  31. package/dist/core/export-html/template.css +43 -13
  32. package/dist/core/export-html/template.html +1 -0
  33. package/dist/core/export-html/template.js +107 -0
  34. package/dist/core/export-html/tool-renderer.js.map +1 -1
  35. package/dist/core/extensions/index.d.ts +1 -1
  36. package/dist/core/extensions/index.d.ts.map +1 -1
  37. package/dist/core/extensions/index.js.map +1 -1
  38. package/dist/core/extensions/loader.d.ts.map +1 -1
  39. package/dist/core/extensions/loader.js +4 -4
  40. package/dist/core/extensions/loader.js.map +1 -1
  41. package/dist/core/extensions/runner.d.ts +1 -1
  42. package/dist/core/extensions/runner.d.ts.map +1 -1
  43. package/dist/core/extensions/runner.js +62 -56
  44. package/dist/core/extensions/runner.js.map +1 -1
  45. package/dist/core/extensions/types.d.ts +4 -3
  46. package/dist/core/extensions/types.d.ts.map +1 -1
  47. package/dist/core/extensions/types.js.map +1 -1
  48. package/dist/core/extensions/wrapper.js.map +1 -1
  49. package/dist/core/footer-data-provider.d.ts +9 -2
  50. package/dist/core/footer-data-provider.d.ts.map +1 -1
  51. package/dist/core/footer-data-provider.js +92 -20
  52. package/dist/core/footer-data-provider.js.map +1 -1
  53. package/dist/core/index.d.ts +1 -1
  54. package/dist/core/index.d.ts.map +1 -1
  55. package/dist/core/index.js.map +1 -1
  56. package/dist/core/keybindings.d.ts +268 -51
  57. package/dist/core/keybindings.d.ts.map +1 -1
  58. package/dist/core/keybindings.js +220 -143
  59. package/dist/core/keybindings.js.map +1 -1
  60. package/dist/core/messages.js.map +1 -1
  61. package/dist/core/model-registry.d.ts +1 -0
  62. package/dist/core/model-registry.d.ts.map +1 -1
  63. package/dist/core/model-registry.js +29 -21
  64. package/dist/core/model-registry.js.map +1 -1
  65. package/dist/core/model-resolver.d.ts.map +1 -1
  66. package/dist/core/model-resolver.js +4 -4
  67. package/dist/core/model-resolver.js.map +1 -1
  68. package/dist/core/package-manager.d.ts +2 -0
  69. package/dist/core/package-manager.d.ts.map +1 -1
  70. package/dist/core/package-manager.js +42 -7
  71. package/dist/core/package-manager.js.map +1 -1
  72. package/dist/core/prompt-templates.js.map +1 -1
  73. package/dist/core/resolve-config-value.js.map +1 -1
  74. package/dist/core/resource-loader.js +0 -37
  75. package/dist/core/resource-loader.js.map +1 -1
  76. package/dist/core/sdk.d.ts +2 -2
  77. package/dist/core/sdk.d.ts.map +1 -1
  78. package/dist/core/sdk.js +4 -4
  79. package/dist/core/sdk.js.map +1 -1
  80. package/dist/core/session-manager.d.ts +5 -0
  81. package/dist/core/session-manager.d.ts.map +1 -1
  82. package/dist/core/session-manager.js +8 -12
  83. package/dist/core/session-manager.js.map +1 -1
  84. package/dist/core/settings-manager.js +7 -16
  85. package/dist/core/settings-manager.js.map +1 -1
  86. package/dist/core/skills.js.map +1 -1
  87. package/dist/core/system-prompt.js.map +1 -1
  88. package/dist/core/timings.js.map +1 -1
  89. package/dist/core/tools/bash.js.map +1 -1
  90. package/dist/core/tools/edit-diff.js.map +1 -1
  91. package/dist/core/tools/edit.d.ts.map +1 -1
  92. package/dist/core/tools/edit.js +3 -2
  93. package/dist/core/tools/edit.js.map +1 -1
  94. package/dist/core/tools/file-mutation-queue.d.ts +6 -0
  95. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  96. package/dist/core/tools/file-mutation-queue.js +37 -0
  97. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  98. package/dist/core/tools/find.js.map +1 -1
  99. package/dist/core/tools/grep.js.map +1 -1
  100. package/dist/core/tools/index.d.ts +1 -0
  101. package/dist/core/tools/index.d.ts.map +1 -1
  102. package/dist/core/tools/index.js +1 -0
  103. package/dist/core/tools/index.js.map +1 -1
  104. package/dist/core/tools/ls.js.map +1 -1
  105. package/dist/core/tools/path-utils.js.map +1 -1
  106. package/dist/core/tools/read.js.map +1 -1
  107. package/dist/core/tools/truncate.js.map +1 -1
  108. package/dist/core/tools/write.d.ts.map +1 -1
  109. package/dist/core/tools/write.js +6 -3
  110. package/dist/core/tools/write.js.map +1 -1
  111. package/dist/index.d.ts +3 -3
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +2 -2
  114. package/dist/index.js.map +1 -1
  115. package/dist/main.d.ts.map +1 -1
  116. package/dist/main.js +10 -5
  117. package/dist/main.js.map +1 -1
  118. package/dist/migrations.js.map +1 -1
  119. package/dist/modes/interactive/components/armin.js +6 -10
  120. package/dist/modes/interactive/components/armin.js.map +1 -1
  121. package/dist/modes/interactive/components/assistant-message.js +0 -4
  122. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  123. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  124. package/dist/modes/interactive/components/bash-execution.js +8 -14
  125. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  126. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  127. package/dist/modes/interactive/components/bordered-loader.js +1 -4
  128. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  129. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/branch-summary-message.js +3 -5
  131. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  132. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  133. package/dist/modes/interactive/components/compaction-summary-message.js +3 -5
  134. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  135. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  136. package/dist/modes/interactive/components/config-selector.js +14 -23
  137. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  138. package/dist/modes/interactive/components/countdown-timer.js +0 -5
  139. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  140. package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
  141. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  142. package/dist/modes/interactive/components/custom-editor.js +7 -14
  143. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  144. package/dist/modes/interactive/components/custom-message.js +1 -6
  145. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  146. package/dist/modes/interactive/components/daxnuts.js +6 -8
  147. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  148. package/dist/modes/interactive/components/diff.js.map +1 -1
  149. package/dist/modes/interactive/components/dynamic-border.js +0 -1
  150. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  151. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  152. package/dist/modes/interactive/components/extension-editor.js +10 -15
  153. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  154. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  155. package/dist/modes/interactive/components/extension-input.js +7 -13
  156. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  157. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  158. package/dist/modes/interactive/components/extension-selector.js +9 -16
  159. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  160. package/dist/modes/interactive/components/footer.js +1 -3
  161. package/dist/modes/interactive/components/footer.js.map +1 -1
  162. package/dist/modes/interactive/components/index.d.ts +1 -1
  163. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  164. package/dist/modes/interactive/components/index.js +1 -1
  165. package/dist/modes/interactive/components/index.js.map +1 -1
  166. package/dist/modes/interactive/components/keybinding-hints.d.ts +3 -36
  167. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  168. package/dist/modes/interactive/components/keybinding-hints.js +5 -44
  169. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  170. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  171. package/dist/modes/interactive/components/login-dialog.js +9 -15
  172. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  173. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  174. package/dist/modes/interactive/components/model-selector.js +20 -28
  175. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  176. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  177. package/dist/modes/interactive/components/oauth-selector.js +8 -13
  178. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  179. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  180. package/dist/modes/interactive/components/scoped-models-selector.js +13 -17
  181. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  182. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  183. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  184. package/dist/modes/interactive/components/session-selector.js +65 -93
  185. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  186. package/dist/modes/interactive/components/settings-selector.js +0 -2
  187. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  188. package/dist/modes/interactive/components/show-images-selector.js +0 -1
  189. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  190. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  191. package/dist/modes/interactive/components/skill-invocation-message.js +3 -5
  192. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  193. package/dist/modes/interactive/components/theme-selector.js +0 -2
  194. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  195. package/dist/modes/interactive/components/thinking-selector.js +0 -1
  196. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  197. package/dist/modes/interactive/components/tool-execution.d.ts +7 -0
  198. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  199. package/dist/modes/interactive/components/tool-execution.js +57 -28
  200. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  201. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  202. package/dist/modes/interactive/components/tree-selector.js +32 -46
  203. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  204. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  205. package/dist/modes/interactive/components/user-message-selector.js +9 -12
  206. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  207. package/dist/modes/interactive/components/user-message.js.map +1 -1
  208. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  209. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  210. package/dist/modes/interactive/interactive-mode.js +155 -165
  211. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  212. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  213. package/dist/modes/interactive/theme/theme.js +61 -42
  214. package/dist/modes/interactive/theme/theme.js.map +1 -1
  215. package/dist/modes/print-mode.js.map +1 -1
  216. package/dist/modes/rpc/jsonl.js.map +1 -1
  217. package/dist/modes/rpc/rpc-client.js +6 -7
  218. package/dist/modes/rpc/rpc-client.js.map +1 -1
  219. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  220. package/dist/modes/rpc/rpc-mode.js +4 -1
  221. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  222. package/dist/utils/changelog.js.map +1 -1
  223. package/dist/utils/child-process.js.map +1 -1
  224. package/dist/utils/clipboard-image.js.map +1 -1
  225. package/dist/utils/clipboard.js.map +1 -1
  226. package/dist/utils/exif-orientation.js.map +1 -1
  227. package/dist/utils/frontmatter.js.map +1 -1
  228. package/dist/utils/git.js.map +1 -1
  229. package/dist/utils/image-convert.js.map +1 -1
  230. package/dist/utils/image-resize.js.map +1 -1
  231. package/dist/utils/mime.js.map +1 -1
  232. package/dist/utils/photon.js.map +1 -1
  233. package/dist/utils/shell.js.map +1 -1
  234. package/dist/utils/sleep.js.map +1 -1
  235. package/dist/utils/tools-manager.js.map +1 -1
  236. package/docs/extensions.md +42 -5
  237. package/docs/keybindings.md +101 -112
  238. package/examples/extensions/antigravity-image-gen.ts +5 -3
  239. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  240. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  241. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  242. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  243. package/examples/extensions/subagent/index.ts +28 -6
  244. package/examples/extensions/tool-override.ts +9 -7
  245. package/examples/extensions/truncated-tool.ts +6 -3
  246. package/examples/extensions/with-deps/package-lock.json +2 -2
  247. package/examples/extensions/with-deps/package.json +1 -1
  248. package/package.json +4 -4
@@ -2,11 +2,11 @@ import { spawnSync } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
3
  import { unlink } from "node:fs/promises";
4
4
  import * as os from "node:os";
5
- import { Container, getEditorKeybindings, Input, matchesKey, Spacer, Text, truncateToWidth, visibleWidth, } from "@mariozechner/pi-tui";
5
+ import { Container, getKeybindings, Input, Spacer, Text, truncateToWidth, visibleWidth, } from "@mariozechner/pi-tui";
6
6
  import { KeybindingsManager } from "../../../core/keybindings.js";
7
7
  import { theme } from "../theme/theme.js";
8
8
  import { DynamicBorder } from "./dynamic-border.js";
9
- import { appKey, appKeyHint, keyHint } from "./keybinding-hints.js";
9
+ import { keyHint, keyText } from "./keybinding-hints.js";
10
10
  import { filterAndSortSessions, hasSessionName } from "./session-selector-search.js";
11
11
  function shortenPath(path) {
12
12
  const home = os.homedir();
@@ -38,23 +38,17 @@ function formatSessionDate(date) {
38
38
  return `${Math.floor(diffDays / 365)}y`;
39
39
  }
40
40
  class SessionSelectorHeader {
41
- scope;
42
- sortMode;
43
- nameFilter;
44
- keybindings;
45
- requestRender;
46
- loading = false;
47
- loadProgress = null;
48
- showPath = false;
49
- confirmingDeletePath = null;
50
- statusMessage = null;
51
- statusTimeout = null;
52
- showRenameHint = false;
53
- constructor(scope, sortMode, nameFilter, keybindings, requestRender) {
41
+ constructor(scope, sortMode, nameFilter, requestRender) {
42
+ this.loading = false;
43
+ this.loadProgress = null;
44
+ this.showPath = false;
45
+ this.confirmingDeletePath = null;
46
+ this.statusMessage = null;
47
+ this.statusTimeout = null;
48
+ this.showRenameHint = false;
54
49
  this.scope = scope;
55
50
  this.sortMode = sortMode;
56
51
  this.nameFilter = nameFilter;
57
- this.keybindings = keybindings;
58
52
  this.requestRender = requestRender;
59
53
  }
60
54
  setScope(scope) {
@@ -127,7 +121,7 @@ class SessionSelectorHeader {
127
121
  let hintLine1;
128
122
  let hintLine2;
129
123
  if (this.confirmingDeletePath !== null) {
130
- const confirmHint = "Delete session? [Enter] confirm · [Esc/Ctrl+C] cancel";
124
+ const confirmHint = `Delete session? ${keyHint("tui.select.confirm", "confirm")} · ${keyHint("tui.select.cancel", "cancel")}`;
131
125
  hintLine1 = theme.fg("error", truncateToWidth(confirmHint, width, "…"));
132
126
  hintLine2 = "";
133
127
  }
@@ -139,15 +133,15 @@ class SessionSelectorHeader {
139
133
  else {
140
134
  const pathState = this.showPath ? "(on)" : "(off)";
141
135
  const sep = theme.fg("muted", " · ");
142
- const hint1 = keyHint("tab", "scope") + sep + theme.fg("muted", 're:<pattern> regex · "phrase" exact');
136
+ const hint1 = keyHint("tui.input.tab", "scope") + sep + theme.fg("muted", 're:<pattern> regex · "phrase" exact');
143
137
  const hint2Parts = [
144
- keyHint("toggleSessionSort", "sort"),
145
- appKeyHint(this.keybindings, "toggleSessionNamedFilter", "named"),
146
- keyHint("deleteSession", "delete"),
147
- keyHint("toggleSessionPath", `path ${pathState}`),
138
+ keyHint("app.session.toggleSort", "sort"),
139
+ keyHint("app.session.toggleNamedFilter", "named"),
140
+ keyHint("app.session.delete", "delete"),
141
+ keyHint("app.session.togglePath", `path ${pathState}`),
148
142
  ];
149
143
  if (this.showRenameHint) {
150
- hint2Parts.push(keyHint("renameSession", "rename"));
144
+ hint2Parts.push(keyHint("app.session.rename", "rename"));
151
145
  }
152
146
  const hint2 = hint2Parts.join(sep);
153
147
  hintLine1 = truncateToWidth(hint1, width, "…");
@@ -213,31 +207,6 @@ class SessionList {
213
207
  const selected = this.filteredSessions[this.selectedIndex];
214
208
  return selected?.session.path;
215
209
  }
216
- allSessions = [];
217
- filteredSessions = [];
218
- selectedIndex = 0;
219
- searchInput;
220
- showCwd = false;
221
- sortMode = "threaded";
222
- nameFilter = "all";
223
- keybindings;
224
- showPath = false;
225
- confirmingDeletePath = null;
226
- currentSessionFilePath;
227
- onSelect;
228
- onCancel;
229
- onExit = () => { };
230
- onToggleScope;
231
- onToggleSort;
232
- onToggleNameFilter;
233
- onTogglePath;
234
- onDeleteConfirmationChange;
235
- onDeleteSession;
236
- onRenameSession;
237
- onError;
238
- maxVisible = 10; // Max sessions visible (one line each)
239
- // Focusable implementation - propagate to searchInput for IME cursor positioning
240
- _focused = false;
241
210
  get focused() {
242
211
  return this._focused;
243
212
  }
@@ -246,6 +215,18 @@ class SessionList {
246
215
  this.searchInput.focused = value;
247
216
  }
248
217
  constructor(sessions, showCwd, sortMode, nameFilter, keybindings, currentSessionFilePath) {
218
+ this.allSessions = [];
219
+ this.filteredSessions = [];
220
+ this.selectedIndex = 0;
221
+ this.showCwd = false;
222
+ this.sortMode = "threaded";
223
+ this.nameFilter = "all";
224
+ this.showPath = false;
225
+ this.confirmingDeletePath = null;
226
+ this.onExit = () => { };
227
+ this.maxVisible = 10; // Max sessions visible (one line each)
228
+ // Focusable implementation - propagate to searchInput for IME cursor positioning
229
+ this._focused = false;
249
230
  this.allSessions = sessions;
250
231
  this.filteredSessions = [];
251
232
  this.searchInput = new Input();
@@ -322,7 +303,7 @@ class SessionList {
322
303
  if (this.filteredSessions.length === 0) {
323
304
  let emptyMessage;
324
305
  if (this.nameFilter === "named") {
325
- const toggleKey = appKey(this.keybindings, "toggleSessionNamedFilter");
306
+ const toggleKey = keyText("app.session.toggleNamedFilter");
326
307
  if (this.showCwd) {
327
308
  emptyMessage = ` No named sessions found. Press ${toggleKey} to show all.`;
328
309
  }
@@ -417,50 +398,49 @@ class SessionList {
417
398
  return parts.join("") + branch;
418
399
  }
419
400
  handleInput(keyData) {
420
- const kb = getEditorKeybindings();
401
+ const kb = getKeybindings();
421
402
  // Handle delete confirmation state first - intercept all keys
422
403
  if (this.confirmingDeletePath !== null) {
423
- if (kb.matches(keyData, "selectConfirm")) {
404
+ if (kb.matches(keyData, "tui.select.confirm")) {
424
405
  const pathToDelete = this.confirmingDeletePath;
425
406
  this.setConfirmingDeletePath(null);
426
407
  void this.onDeleteSession?.(pathToDelete);
427
408
  return;
428
409
  }
429
- // Allow both Escape and Ctrl+C to cancel (consistent with pi UX)
430
- if (kb.matches(keyData, "selectCancel") || matchesKey(keyData, "ctrl+c")) {
410
+ if (kb.matches(keyData, "tui.select.cancel")) {
431
411
  this.setConfirmingDeletePath(null);
432
412
  return;
433
413
  }
434
414
  // Ignore all other keys while confirming
435
415
  return;
436
416
  }
437
- if (kb.matches(keyData, "tab")) {
417
+ if (kb.matches(keyData, "tui.input.tab")) {
438
418
  if (this.onToggleScope) {
439
419
  this.onToggleScope();
440
420
  }
441
421
  return;
442
422
  }
443
- if (kb.matches(keyData, "toggleSessionSort")) {
423
+ if (kb.matches(keyData, "app.session.toggleSort")) {
444
424
  this.onToggleSort?.();
445
425
  return;
446
426
  }
447
- if (this.keybindings.matches(keyData, "toggleSessionNamedFilter")) {
427
+ if (this.keybindings.matches(keyData, "app.session.toggleNamedFilter")) {
448
428
  this.onToggleNameFilter?.();
449
429
  return;
450
430
  }
451
431
  // Ctrl+P: toggle path display
452
- if (kb.matches(keyData, "toggleSessionPath")) {
432
+ if (kb.matches(keyData, "app.session.togglePath")) {
453
433
  this.showPath = !this.showPath;
454
434
  this.onTogglePath?.(this.showPath);
455
435
  return;
456
436
  }
457
437
  // Ctrl+D: initiate delete confirmation (useful on terminals that don't distinguish Ctrl+Backspace from Backspace)
458
- if (kb.matches(keyData, "deleteSession")) {
438
+ if (kb.matches(keyData, "app.session.delete")) {
459
439
  this.startDeleteConfirmationForSelectedSession();
460
440
  return;
461
441
  }
462
- // Ctrl+R: rename selected session
463
- if (matchesKey(keyData, "ctrl+r")) {
442
+ // Rename selected session
443
+ if (kb.matches(keyData, "app.session.rename")) {
464
444
  const selected = this.filteredSessions[this.selectedIndex];
465
445
  if (selected) {
466
446
  this.onRenameSession?.(selected.session.path);
@@ -469,7 +449,7 @@ class SessionList {
469
449
  }
470
450
  // Ctrl+Backspace: non-invasive convenience alias for delete
471
451
  // Only triggers deletion when the query is empty; otherwise it is forwarded to the input
472
- if (kb.matches(keyData, "deleteSessionNoninvasive")) {
452
+ if (kb.matches(keyData, "app.session.deleteNoninvasive")) {
473
453
  if (this.searchInput.getValue().length > 0) {
474
454
  this.searchInput.handleInput(keyData);
475
455
  this.filterSessions(this.searchInput.getValue());
@@ -479,30 +459,30 @@ class SessionList {
479
459
  return;
480
460
  }
481
461
  // Up arrow
482
- if (kb.matches(keyData, "selectUp")) {
462
+ if (kb.matches(keyData, "tui.select.up")) {
483
463
  this.selectedIndex = Math.max(0, this.selectedIndex - 1);
484
464
  }
485
465
  // Down arrow
486
- else if (kb.matches(keyData, "selectDown")) {
466
+ else if (kb.matches(keyData, "tui.select.down")) {
487
467
  this.selectedIndex = Math.min(this.filteredSessions.length - 1, this.selectedIndex + 1);
488
468
  }
489
469
  // Page up - jump up by maxVisible items
490
- else if (kb.matches(keyData, "selectPageUp")) {
470
+ else if (kb.matches(keyData, "tui.select.pageUp")) {
491
471
  this.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisible);
492
472
  }
493
473
  // Page down - jump down by maxVisible items
494
- else if (kb.matches(keyData, "selectPageDown")) {
474
+ else if (kb.matches(keyData, "tui.select.pageDown")) {
495
475
  this.selectedIndex = Math.min(this.filteredSessions.length - 1, this.selectedIndex + this.maxVisible);
496
476
  }
497
477
  // Enter
498
- else if (kb.matches(keyData, "selectConfirm")) {
478
+ else if (kb.matches(keyData, "tui.select.confirm")) {
499
479
  const selected = this.filteredSessions[this.selectedIndex];
500
480
  if (selected && this.onSelect) {
501
481
  this.onSelect(selected.session.path);
502
482
  }
503
483
  }
504
484
  // Escape - cancel
505
- else if (kb.matches(keyData, "selectCancel")) {
485
+ else if (kb.matches(keyData, "tui.select.cancel")) {
506
486
  if (this.onCancel) {
507
487
  this.onCancel();
508
488
  }
@@ -556,8 +536,8 @@ async function deleteSessionFile(sessionPath) {
556
536
  export class SessionSelectorComponent extends Container {
557
537
  handleInput(data) {
558
538
  if (this.mode === "rename") {
559
- const kb = getEditorKeybindings();
560
- if (kb.matches(data, "selectCancel") || matchesKey(data, "ctrl+c")) {
539
+ const kb = getKeybindings();
540
+ if (kb.matches(data, "tui.select.cancel")) {
561
541
  this.exitRenameMode();
562
542
  return;
563
543
  }
@@ -566,28 +546,6 @@ export class SessionSelectorComponent extends Container {
566
546
  }
567
547
  this.sessionList.handleInput(data);
568
548
  }
569
- canRename = true;
570
- sessionList;
571
- header;
572
- keybindings;
573
- scope = "current";
574
- sortMode = "threaded";
575
- nameFilter = "all";
576
- currentSessions = null;
577
- allSessions = null;
578
- currentSessionsLoader;
579
- allSessionsLoader;
580
- onCancel;
581
- requestRender;
582
- renameSession;
583
- currentLoading = false;
584
- allLoading = false;
585
- allLoadSeq = 0;
586
- mode = "list";
587
- renameInput = new Input();
588
- renameTargetPath = null;
589
- // Focusable implementation - propagate to sessionList for IME cursor positioning
590
- _focused = false;
591
549
  get focused() {
592
550
  return this._focused;
593
551
  }
@@ -614,12 +572,26 @@ export class SessionSelectorComponent extends Container {
614
572
  }
615
573
  constructor(currentSessionsLoader, allSessionsLoader, onSelect, onCancel, onExit, requestRender, options, currentSessionFilePath) {
616
574
  super();
575
+ this.canRename = true;
576
+ this.scope = "current";
577
+ this.sortMode = "threaded";
578
+ this.nameFilter = "all";
579
+ this.currentSessions = null;
580
+ this.allSessions = null;
581
+ this.currentLoading = false;
582
+ this.allLoading = false;
583
+ this.allLoadSeq = 0;
584
+ this.mode = "list";
585
+ this.renameInput = new Input();
586
+ this.renameTargetPath = null;
587
+ // Focusable implementation - propagate to sessionList for IME cursor positioning
588
+ this._focused = false;
617
589
  this.keybindings = options?.keybindings ?? KeybindingsManager.create();
618
590
  this.currentSessionsLoader = currentSessionsLoader;
619
591
  this.allSessionsLoader = allSessionsLoader;
620
592
  this.onCancel = onCancel;
621
593
  this.requestRender = requestRender;
622
- this.header = new SessionSelectorHeader(this.scope, this.sortMode, this.nameFilter, this.keybindings, this.requestRender);
594
+ this.header = new SessionSelectorHeader(this.scope, this.sortMode, this.nameFilter, this.requestRender);
623
595
  const renameSession = options?.renameSession;
624
596
  this.renameSession = renameSession;
625
597
  this.canRename = !!renameSession;
@@ -710,7 +682,7 @@ export class SessionSelectorComponent extends Container {
710
682
  panel.addChild(new Spacer(1));
711
683
  panel.addChild(this.renameInput);
712
684
  panel.addChild(new Spacer(1));
713
- panel.addChild(new Text(theme.fg("muted", "Enter to save · Esc/Ctrl+C to cancel"), 1, 0));
685
+ panel.addChild(new Text(theme.fg("muted", `${keyText("tui.select.confirm")} to save · ${keyText("tui.select.cancel")} to cancel`), 1, 0));
714
686
  this.buildBaseLayout(panel, { showHeader: false });
715
687
  this.requestRender();
716
688
  }