@brimveyn/aimux-config 0.4.1 → 0.4.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brimveyn/aimux-config",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "TypeScript configuration API for aimux — keymaps, themes, and backends with a fluent builder.",
5
5
  "keywords": [
6
6
  "aimux",
package/src/actions.ts CHANGED
@@ -15,22 +15,26 @@ function r(
15
15
  export const nextTab: KeyResult = r([{ delta: 1, type: 'move-active-tab' }])
16
16
  export const prevTab: KeyResult = r([{ delta: -1, type: 'move-active-tab' }])
17
17
 
18
- export const newTab: KeyResult = r([{ type: 'open-new-tab-modal' }], [], 'modal.new-tab')
18
+ export const newTab: KeyResult = r(
19
+ [{ type: 'open-new-tab-modal' }],
20
+ [],
21
+ 'modal.new-tab.command-edit'
22
+ )
19
23
  export const renameTab: KeyResult = r([{ type: 'open-rename-tab-modal' }], [], 'modal.rename-tab')
20
24
  export const sessionPicker: KeyResult = r(
21
25
  [{ type: 'open-session-picker' }],
22
26
  [],
23
- 'modal.session-picker'
27
+ 'modal.session-picker.filtering'
24
28
  )
25
29
  export const snippetPicker: KeyResult = r(
26
30
  [{ type: 'open-snippet-picker' }],
27
31
  [],
28
- 'modal.snippet-picker'
32
+ 'modal.snippet-picker.filtering'
29
33
  )
30
34
  export const themePicker: KeyResult = r(
31
35
  [{ type: 'open-theme-picker' }],
32
36
  [{ action: 'open', type: 'apply-theme' }],
33
- 'modal.theme-picker'
37
+ 'modal.theme-picker.filtering'
34
38
  )
35
39
  export function helpModal(scope?: ModeId): KeyResult {
36
40
  return r([{ scope, type: 'open-help-modal' }])
@@ -160,25 +164,13 @@ export function moveModalSelectionWithPreview(
160
164
 
161
165
  export const launchSelectedAssistant: KeyResult = r([], [{ type: 'launch-selected-assistant' }])
162
166
 
163
- export const beginCommandEdit: KeyResult = r(
164
- [{ type: 'begin-command-edit' }],
165
- [],
166
- 'modal.new-tab.command-edit'
167
- )
168
-
169
167
  export const cancelCommandEdit = (returnTo: KeyResult['transition']): KeyResult =>
170
168
  r([{ type: 'cancel-command-edit' }], [], returnTo)
171
169
 
172
- export const commitCommandEdit: KeyResult = r(
173
- [{ type: 'commit-command-edit' }],
174
- [{ type: 'save-custom-command' }],
175
- 'modal.new-tab'
176
- )
177
-
178
170
  export const confirmSelectedSession: KeyResult = r([], [{ type: 'confirm-selected-session' }])
179
171
 
180
172
  export const openCreateSessionModal: KeyResult = r(
181
- [{ type: 'open-create-session-modal' }],
173
+ [{ returnToSessionPicker: true, type: 'open-create-session-modal' }],
182
174
  [],
183
175
  'modal.create-session'
184
176
  )
@@ -190,12 +182,6 @@ export const openRenameSelectedSession: KeyResult = r(
190
182
 
191
183
  export const deleteSelectedSession: KeyResult = r([], [{ type: 'delete-selected-session' }])
192
184
 
193
- export const beginSessionFilter: KeyResult = r(
194
- [{ type: 'begin-session-filter' }],
195
- [],
196
- 'modal.session-picker.filtering'
197
- )
198
-
199
185
  export const openSnippetEditor: KeyResult = r(
200
186
  [{ type: 'open-snippet-editor' }],
201
187
  [],
@@ -217,24 +203,6 @@ export const pasteSnippetToGroup: KeyResult = r(
217
203
  'navigation'
218
204
  )
219
205
 
220
- export const beginSnippetFilter: KeyResult = r(
221
- [{ type: 'begin-snippet-filter' }],
222
- [],
223
- 'modal.snippet-picker.filtering'
224
- )
225
-
226
- export const beginHelpFilter: KeyResult = r(
227
- [{ type: 'begin-help-filter' }],
228
- [],
229
- 'modal.help.filtering'
230
- )
231
-
232
- export const beginThemeFilter: KeyResult = r(
233
- [{ type: 'begin-theme-filter' }],
234
- [],
235
- 'modal.theme-picker.filtering'
236
- )
237
-
238
206
  export const confirmSplit: KeyResult = r([], [{ type: 'confirm-split' }])
239
207
 
240
208
  export const restoreTheme: KeyResult = r(
@@ -256,19 +224,28 @@ export function previewTheme(delta: 1 | -1): KeyResult {
256
224
  )
257
225
  }
258
226
 
227
+ export const toggleTransparent: KeyResult = r([], [{ type: 'toggle-transparent' }])
228
+
259
229
  export const switchField: KeyResult = r([{ type: 'switch-create-session-field' }])
260
230
  export const selectDirectory: KeyResult = r([{ type: 'select-directory' }])
261
231
 
262
232
  export const backToSessionPicker: KeyResult = r(
263
233
  [{ type: 'open-session-picker' }],
264
234
  [],
265
- 'modal.session-picker'
235
+ 'modal.session-picker.filtering'
266
236
  )
267
237
 
238
+ export const createSessionEscape: ActionFn = (ctx: ModeContext) => {
239
+ if (ctx.state.modal.type === 'create-session' && !ctx.state.modal.returnToSessionPicker) {
240
+ return r([{ type: 'close-modal' }], [], 'navigation')
241
+ }
242
+ return r([{ type: 'open-session-picker' }], [], 'modal.session-picker.filtering')
243
+ }
244
+
268
245
  export const backToSnippetPicker: KeyResult = r(
269
246
  [{ type: 'open-snippet-picker' }],
270
247
  [],
271
- 'modal.snippet-picker'
248
+ 'modal.snippet-picker.filtering'
272
249
  )
273
250
 
274
251
  export const saveSnippetEditor: KeyResult = r(
@@ -277,6 +254,18 @@ export const saveSnippetEditor: KeyResult = r(
277
254
  'navigation'
278
255
  )
279
256
 
257
+ export const saveCustomCommand: KeyResult = r(
258
+ [],
259
+ [{ type: 'save-custom-command' }],
260
+ 'modal.new-tab.command-edit'
261
+ )
262
+
263
+ export const cancelEditCustomCommand: KeyResult = r(
264
+ [{ type: 'cancel-command-edit' }],
265
+ [],
266
+ 'modal.new-tab.command-edit'
267
+ )
268
+
280
269
  // ---------------------------------------------------------------------------
281
270
  // Update-available modal
282
271
  // ---------------------------------------------------------------------------
@@ -329,10 +318,10 @@ export const confirmSessionRename: ActionFn = (ctx: ModeContext) => {
329
318
  return r(
330
319
  [{ type: 'open-session-picker' }],
331
320
  [{ name: trimmed, sessionId, type: 'rename-session' }],
332
- 'modal.session-picker'
321
+ 'modal.session-picker.filtering'
333
322
  )
334
323
  }
335
- return r([{ type: 'open-session-picker' }], [], 'modal.session-picker')
324
+ return r([{ type: 'open-session-picker' }], [], 'modal.session-picker.filtering')
336
325
  }
337
326
 
338
327
  // Rename tab modal
@@ -457,6 +446,14 @@ export const toggleGitFileListMode: ActionFn = (ctx: ModeContext) => {
457
446
  )
458
447
  }
459
448
 
449
+ export const toggleTreeCompaction: ActionFn = (ctx: ModeContext) => {
450
+ const enabled = !ctx.state.gitPane.treeCompaction
451
+ return r(
452
+ [{ type: 'git-mode-toggle-tree-compaction' }],
453
+ [{ enabled, type: 'persist-git-tree-compaction' }]
454
+ )
455
+ }
456
+
460
457
  export function scrollGitDiff(delta: number): KeyResult {
461
458
  return r([], [{ delta, type: 'scroll-git-diff' }])
462
459
  }
package/src/defaults.ts CHANGED
@@ -88,6 +88,7 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
88
88
  .map('p', actions.gitPush, 'Push')
89
89
  .map('v', actions.toggleGitDiffView, 'Toggle split/stacked')
90
90
  .map('t', actions.toggleGitFileListMode, 'Toggle flat/tree')
91
+ .map('T', actions.toggleTreeCompaction, 'Toggle tree compaction')
91
92
  .map(']', actions.shiftGitHeadOffset(1), 'Older commit')
92
93
  .map('[', actions.shiftGitHeadOffset(-1), 'Newer commit')
93
94
  .map('?', actions.helpModal('git-mode'), 'Help')
@@ -110,26 +111,11 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
110
111
  )
111
112
 
112
113
  // -----------------------------------------------------------------------
113
- // Modal: help
114
- // -----------------------------------------------------------------------
115
- .mode('modal.help', (m) =>
116
- m
117
- .map('<Esc>', actions.closeOverlayModal, 'Close')
118
- .map('j', actions.moveModalSelection(1), 'Next')
119
- .map('k', actions.moveModalSelection(-1), 'Prev')
120
- .map('<Down>', actions.moveModalSelection(1))
121
- .map('<Up>', actions.moveModalSelection(-1))
122
- .map('<C-n>', actions.moveModalSelection(1))
123
- .map('<C-p>', actions.moveModalSelection(-1))
124
- .map('/', actions.beginHelpFilter, 'Filter')
125
- )
126
-
127
- // -----------------------------------------------------------------------
128
- // Modal: help filtering
114
+ // Modal: help (always in filter mode via Picker)
129
115
  // -----------------------------------------------------------------------
130
116
  .mode('modal.help.filtering', (m) =>
131
117
  m
132
- .map('<Esc>', actions.cancelCommandEdit('modal.help'), 'Cancel')
118
+ .map('<Esc>', actions.closeOverlayModal, 'Close')
133
119
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
134
120
  .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
135
121
  .map('<Down>', actions.moveModalSelection(1))
@@ -138,32 +124,17 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
138
124
  )
139
125
 
140
126
  // -----------------------------------------------------------------------
141
- // Modal: theme-picker
142
- // -----------------------------------------------------------------------
143
- .mode('modal.theme-picker', (m) =>
144
- m
145
- .map('<Esc>', actions.restoreTheme, 'Cancel')
146
- .map('j', actions.previewTheme(1), 'Next')
147
- .map('k', actions.previewTheme(-1), 'Prev')
148
- .map('<Down>', actions.previewTheme(1))
149
- .map('<Up>', actions.previewTheme(-1))
150
- .map('<C-n>', actions.previewTheme(1))
151
- .map('<C-p>', actions.previewTheme(-1))
152
- .map('<CR>', actions.confirmTheme, 'Confirm')
153
- .map('/', actions.beginThemeFilter, 'Filter')
154
- )
155
-
156
- // -----------------------------------------------------------------------
157
- // Modal: theme-picker filtering
127
+ // Modal: theme-picker (always in filter mode via Picker)
158
128
  // -----------------------------------------------------------------------
159
129
  .mode('modal.theme-picker.filtering', (m) =>
160
130
  m
161
- .map('<Esc>', actions.cancelCommandEdit('modal.theme-picker'), 'Cancel')
131
+ .map('<Esc>', actions.restoreTheme, 'Cancel')
162
132
  .map('<C-n>', actions.previewTheme(1), 'Next')
163
133
  .map('<C-p>', actions.previewTheme(-1), 'Prev')
164
134
  .map('<Down>', actions.previewTheme(1))
165
135
  .map('<Up>', actions.previewTheme(-1))
166
136
  .map('<CR>', actions.confirmTheme, 'Confirm')
137
+ .map('<C-t>', actions.toggleTransparent, 'Toggle transparent')
167
138
  .passthrough()
168
139
  )
169
140
 
@@ -175,8 +146,6 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
175
146
  .map('<Esc>', actions.closeModal, 'Cancel')
176
147
  .map('l', actions.moveModalSelection(1), 'Next')
177
148
  .map('h', actions.moveModalSelection(-1), 'Prev')
178
- .map('j', actions.moveModalSelection(1))
179
- .map('k', actions.moveModalSelection(-1))
180
149
  .map('<Right>', actions.moveModalSelection(1))
181
150
  .map('<Left>', actions.moveModalSelection(-1))
182
151
  .map('<Down>', actions.moveModalSelection(1))
@@ -197,28 +166,12 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
197
166
  )
198
167
 
199
168
  // -----------------------------------------------------------------------
200
- // Modal: new-tab
169
+ // Modal: new-tab (always in filter mode via Picker)
201
170
  // -----------------------------------------------------------------------
202
- .mode('modal.new-tab', (m) =>
171
+ .mode('modal.new-tab.command-edit', (m) =>
203
172
  m
204
173
  .map('<Esc>', actions.closeModal, 'Cancel')
205
- .map('j', actions.moveModalSelection(1), 'Next')
206
- .map('k', actions.moveModalSelection(-1), 'Prev')
207
- .map('<Down>', actions.moveModalSelection(1))
208
- .map('<Up>', actions.moveModalSelection(-1))
209
- .map('<C-n>', actions.moveModalSelection(1))
210
- .map('<C-p>', actions.moveModalSelection(-1))
211
174
  .map('<CR>', actions.launchSelectedAssistant, 'Launch')
212
- .map('e', actions.beginCommandEdit, 'Edit command')
213
- )
214
-
215
- // -----------------------------------------------------------------------
216
- // Modal: new-tab command-edit
217
- // -----------------------------------------------------------------------
218
- .mode('modal.new-tab.command-edit', (m) =>
219
- m
220
- .map('<Esc>', actions.cancelCommandEdit('modal.new-tab'), 'Cancel')
221
- .map('<CR>', actions.commitCommandEdit, 'Save')
222
175
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
223
176
  .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
224
177
  .map('<Down>', actions.moveModalSelection(1))
@@ -226,31 +179,19 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
226
179
  .passthrough()
227
180
  )
228
181
 
229
- // -----------------------------------------------------------------------
230
- // Modal: session-picker
231
- // -----------------------------------------------------------------------
232
- .mode('modal.session-picker', (m) =>
182
+ .mode('modal.new-tab.editing-command', (m) =>
233
183
  m
234
- .map('<Esc>', actions.sessionPickerEscape, 'Cancel')
235
- .map('j', actions.moveModalSelection(1), 'Next')
236
- .map('k', actions.moveModalSelection(-1), 'Prev')
237
- .map('<Down>', actions.moveModalSelection(1))
238
- .map('<Up>', actions.moveModalSelection(-1))
239
- .map('<C-n>', actions.moveModalSelection(1))
240
- .map('<C-p>', actions.moveModalSelection(-1))
241
- .map('<CR>', actions.confirmSelectedSession, 'Open')
242
- .map('n', actions.openCreateSessionModal, 'New')
243
- .map('r', actions.openRenameSelectedSession, 'Rename')
244
- .map('d', actions.deleteSelectedSession, 'Delete')
245
- .map('/', actions.beginSessionFilter, 'Filter')
184
+ .map('<Esc>', actions.cancelEditCustomCommand, 'Cancel')
185
+ .map('<CR>', actions.saveCustomCommand, 'Save')
186
+ .passthrough()
246
187
  )
247
188
 
248
189
  // -----------------------------------------------------------------------
249
- // Modal: session-picker filtering
190
+ // Modal: session-picker (always in filter mode via Picker)
250
191
  // -----------------------------------------------------------------------
251
192
  .mode('modal.session-picker.filtering', (m) =>
252
193
  m
253
- .map('<Esc>', actions.cancelCommandEdit('modal.session-picker'), 'Cancel')
194
+ .map('<Esc>', actions.sessionPickerEscape, 'Cancel')
254
195
  .map('<CR>', actions.confirmSelectedSession, 'Open')
255
196
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
256
197
  .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
@@ -274,7 +215,7 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
274
215
  // -----------------------------------------------------------------------
275
216
  .mode('modal.create-session', (m) =>
276
217
  m
277
- .map('<Esc>', actions.backToSessionPicker, 'Cancel')
218
+ .map('<Esc>', actions.createSessionEscape, 'Cancel')
278
219
  .map('<Tab>', actions.switchField, 'Next field')
279
220
  .map('<CR>', actions.confirmCreateSession, 'Confirm')
280
221
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
@@ -285,32 +226,11 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
285
226
  )
286
227
 
287
228
  // -----------------------------------------------------------------------
288
- // Modal: snippet-picker
289
- // -----------------------------------------------------------------------
290
- .mode('modal.snippet-picker', (m) =>
291
- m
292
- .map('<Esc>', actions.closeModal, 'Cancel')
293
- .map('j', actions.moveModalSelection(1), 'Next')
294
- .map('k', actions.moveModalSelection(-1), 'Prev')
295
- .map('<Down>', actions.moveModalSelection(1))
296
- .map('<Up>', actions.moveModalSelection(-1))
297
- .map('<C-n>', actions.moveModalSelection(1))
298
- .map('<C-p>', actions.moveModalSelection(-1))
299
- .map('<CR>', actions.pasteSelectedSnippet, 'Send')
300
- .map('a', actions.pasteSnippetToGroup, 'Send to group')
301
- .map('n', actions.openSnippetEditor, 'New')
302
- .map('r', actions.editSelectedSnippet, 'Edit')
303
- .map('e', actions.editSelectedSnippet)
304
- .map('d', actions.deleteSelectedSnippet, 'Delete')
305
- .map('/', actions.beginSnippetFilter, 'Filter')
306
- )
307
-
308
- // -----------------------------------------------------------------------
309
- // Modal: snippet-picker filtering
229
+ // Modal: snippet-picker (always in filter mode via Picker)
310
230
  // -----------------------------------------------------------------------
311
231
  .mode('modal.snippet-picker.filtering', (m) =>
312
232
  m
313
- .map('<Esc>', actions.cancelCommandEdit('modal.snippet-picker'), 'Cancel')
233
+ .map('<Esc>', actions.closeModal, 'Cancel')
314
234
  .map('<CR>', actions.snippetFilterPaste, 'Send')
315
235
  .map('<C-a>', actions.snippetFilterPasteToGroup, 'Send to group')
316
236
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
@@ -341,10 +261,8 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
341
261
  .mode('modal.split-picker', (m) =>
342
262
  m
343
263
  .map('<Esc>', actions.closeModal, 'Cancel')
344
- .map('j', actions.moveModalSelection(1), 'Next')
345
- .map('k', actions.moveModalSelection(-1), 'Prev')
346
- .map('<Down>', actions.moveModalSelection(1))
347
- .map('<Up>', actions.moveModalSelection(-1))
264
+ .map('<Down>', actions.moveModalSelection(1), 'Next')
265
+ .map('<Up>', actions.moveModalSelection(-1), 'Prev')
348
266
  .map('<C-n>', actions.moveModalSelection(1))
349
267
  .map('<C-p>', actions.moveModalSelection(-1))
350
268
  .map('<CR>', actions.confirmSplit, 'Confirm')
package/src/types.ts CHANGED
@@ -12,19 +12,15 @@ export type ModeId =
12
12
  | 'navigation'
13
13
  | 'terminal-input'
14
14
  | 'git-mode'
15
- | 'modal.new-tab'
16
15
  | 'modal.new-tab.command-edit'
17
- | 'modal.session-picker'
16
+ | 'modal.new-tab.editing-command'
18
17
  | 'modal.session-picker.filtering'
19
18
  | 'modal.session-name'
20
19
  | 'modal.create-session'
21
20
  | 'modal.rename-tab'
22
- | 'modal.snippet-picker'
23
21
  | 'modal.snippet-picker.filtering'
24
22
  | 'modal.snippet-editor'
25
- | 'modal.theme-picker'
26
23
  | 'modal.theme-picker.filtering'
27
- | 'modal.help'
28
24
  | 'modal.help.filtering'
29
25
  | 'modal.split-picker'
30
26
  | 'modal.git-commit'
@@ -34,8 +30,18 @@ export type ModeId =
34
30
 
35
31
  export type BuiltinAssistantId = 'claude' | 'codex' | 'opencode' | 'terminal'
36
32
  export type AssistantId = BuiltinAssistantId | (string & {})
37
- export type TabStatus = 'starting' | 'running' | 'disconnected' | 'exited' | 'error'
38
- export type TabActivity = 'busy' | 'idle'
33
+ export type TabStatus = 'starting' | 'running' | 'disconnected' | 'error'
34
+
35
+ /**
36
+ * Status values that may appear in legacy on-disk workspace snapshots but are
37
+ * not produced by the running app anymore.
38
+ */
39
+ export type LegacyPersistedTabStatus = TabStatus | 'exited'
40
+ export type TabActivity = 'working' | 'waiting-input' | 'idle'
41
+ export interface SessionStatus {
42
+ working: boolean
43
+ waiting: boolean
44
+ }
39
45
  export type FocusMode = 'navigation' | 'terminal-input' | 'modal' | 'command-edit' | 'git'
40
46
  export type SplitDirection = 'horizontal' | 'vertical'
41
47
 
@@ -89,7 +95,7 @@ export interface PersistedTabSnapshot {
89
95
  assistant: AssistantId
90
96
  title: string
91
97
  command: string
92
- status: Exclude<TabStatus, 'disconnected'>
98
+ status: Exclude<LegacyPersistedTabStatus, 'disconnected'>
93
99
  buffer: string
94
100
  viewport?: TerminalSnapshot
95
101
  terminalModes: TerminalModeState
@@ -165,8 +171,10 @@ export interface GitPaneState {
165
171
  ratio: number
166
172
  diffModeRatio: number
167
173
  fileListMode: GitFileListMode
174
+ treeCompaction: boolean
168
175
  path: GitPanePathConfig
169
176
  diffCount: GitPaneDiffCountConfig
177
+ prefetchRadius: number
170
178
  }
171
179
 
172
180
  export type GitFileStatus = 'M' | 'A' | 'D' | 'R' | 'C' | 'U' | '?'
@@ -215,6 +223,10 @@ export interface GitModeState {
215
223
  selectedEntryKey: string | null
216
224
  collapsedFolders: Record<string, true>
217
225
  diffs: Record<string, DiffData>
226
+ /** Parsed diff cache (internal); detailed shape lives in src/state/types. */
227
+ parsedFiles: Record<string, { hash: string; file: unknown }>
228
+ /** Syntax-highlight cache (internal). */
229
+ highlights: Record<string, { hash: string; themeId: string; add: unknown; del: unknown }>
218
230
  loading: Record<string, boolean>
219
231
  pendingDeletePath: string | null
220
232
  actionMessage: string | null
@@ -238,6 +250,7 @@ export interface ModalClosed extends ModalBase {
238
250
 
239
251
  export interface ModalNewTab extends ModalBase {
240
252
  type: 'new-tab'
253
+ editingCommand: AssistantId | null
241
254
  }
242
255
  export interface ModalSessionPicker extends ModalBase {
243
256
  type: 'session-picker'
@@ -270,6 +283,7 @@ export interface ModalCreateSession extends ModalBase {
270
283
  pendingProjectPath: string | null
271
284
  activeField: 'directory' | 'name'
272
285
  nameBuffer: string
286
+ returnToSessionPicker: boolean
273
287
  }
274
288
  export interface ModalGitCommit extends ModalBase {
275
289
  type: 'git-commit'
@@ -322,7 +336,7 @@ export interface AppState {
322
336
  tabGroupMap: Record<string, string>
323
337
  sessions: SessionRecord[]
324
338
  currentSessionId: string | null
325
- sessionsBusy: Record<string, boolean>
339
+ sessionStatuses: Record<string, SessionStatus>
326
340
  sessionBar: SessionBarState
327
341
  snippets: SnippetRecord[]
328
342
  focusMode: FocusMode
@@ -346,21 +360,15 @@ export type ModalAction =
346
360
  | { type: 'open-session-name-modal'; sessionTargetId?: string; initialName?: string }
347
361
  | { type: 'close-modal' }
348
362
  | { type: 'move-modal-selection'; delta: number }
349
- | { type: 'begin-command-edit' }
350
363
  | { type: 'update-command-edit'; char: string }
351
- | { type: 'commit-command-edit' }
352
364
  | { type: 'cancel-command-edit' }
353
- | { type: 'open-create-session-modal' }
365
+ | { type: 'open-create-session-modal'; returnToSessionPicker: boolean }
354
366
  | { type: 'set-directory-results'; results: DirectoryResult[] }
355
367
  | { type: 'switch-create-session-field' }
356
368
  | { type: 'select-directory' }
357
- | { type: 'begin-session-filter' }
358
369
  | { type: 'open-rename-tab-modal' }
359
370
  | { type: 'open-snippet-picker' }
360
371
  | { type: 'open-snippet-editor'; snippetId?: string }
361
- | { type: 'begin-snippet-filter' }
362
- | { type: 'begin-help-filter' }
363
- | { type: 'begin-theme-filter' }
364
372
  | { type: 'set-help-entry-count'; count: number }
365
373
  | { type: 'set-theme-entry-count'; count: number }
366
374
  | { type: 'open-theme-picker' }
@@ -373,7 +381,7 @@ export type SessionAction =
373
381
  | { type: 'rename-session-record'; sessionId: string; name: string }
374
382
  | { type: 'delete-session-record'; sessionId: string }
375
383
  | { type: 'reorder-sessions'; orderedIds: string[] }
376
- | { type: 'set-session-busy'; sessionId: string; busy: boolean }
384
+ | { type: 'set-session-status'; sessionId: string; status: SessionStatus }
377
385
 
378
386
  export type TabAction =
379
387
  | { type: 'add-tab'; tab: TabSession }
@@ -400,7 +408,6 @@ export type TabAction =
400
408
  terminalModes: TerminalModeState
401
409
  }
402
410
  | { type: 'set-tab-activity'; tabId: string; activity?: TabActivity }
403
- | { type: 'set-tab-status'; tabId: string; status: TabStatus; exitCode?: number }
404
411
  | { type: 'set-tab-error'; tabId: string; message: string }
405
412
 
406
413
  export type LayoutAction =
@@ -464,7 +471,8 @@ export type GitModeAction =
464
471
  | { type: 'git-mode-collapse-selection' }
465
472
  | { type: 'git-mode-expand-selection' }
466
473
  | { type: 'git-mode-toggle-file-list-mode' }
467
- | { type: 'git-mode-set-diff'; key: string; diff: DiffData }
474
+ | { type: 'git-mode-toggle-tree-compaction' }
475
+ | { type: 'git-mode-set-diff'; key: string; diff: DiffData; hash: string }
468
476
  | { type: 'git-mode-set-loading'; key: string; loading: boolean }
469
477
  | { type: 'git-mode-set-pending-delete'; path: string | null }
470
478
  | { type: 'git-mode-clear-diff-cache'; path: string }
@@ -529,6 +537,7 @@ export type SideEffect =
529
537
  | { type: 'scroll-git-diff'; delta: number }
530
538
  | { type: 'persist-git-diff-mode-ratio'; ratio: number }
531
539
  | { type: 'persist-git-file-list-mode'; mode: GitFileListMode }
540
+ | { type: 'persist-git-tree-compaction'; enabled: boolean }
532
541
  | { type: 'git-stage'; path: string }
533
542
  | { type: 'git-unstage'; path: string }
534
543
  | { type: 'git-restore'; path: string }
@@ -537,6 +546,7 @@ export type SideEffect =
537
546
  | { type: 'git-push' }
538
547
  | { type: 'confirm-update-selection' }
539
548
  | { type: 'switch-session-by-index'; index: number }
549
+ | { type: 'toggle-transparent' }
540
550
 
541
551
  // ─── Key input / KeyResult / ModeContext ──────────────────────────────────────
542
552
 
@@ -787,8 +797,11 @@ interface GitPaneBaseConfig {
787
797
  ratio?: number
788
798
  diffModeRatio?: number
789
799
  fileListMode?: GitFileListMode
800
+ treeCompaction?: boolean
790
801
  path?: GitPanePathConfig
791
802
  diffCount?: GitPaneDiffCountConfig
803
+ /** Prefetch N neighbouring diffs around the cursor; 0 disables. */
804
+ prefetchRadius?: number
792
805
  }
793
806
 
794
807
  export interface GitPaneEmbeddedConfig extends GitPaneBaseConfig {