@brimveyn/aimux-config 0.6.9 → 0.6.11
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 +1 -1
- package/src/actions.ts +64 -10
- package/src/defaults.ts +33 -0
- package/src/types.ts +90 -8
package/package.json
CHANGED
package/src/actions.ts
CHANGED
|
@@ -195,7 +195,7 @@ export const launchSelectedAssistant: ActionFn = (ctx: ModeContext) => {
|
|
|
195
195
|
ctx.state.modal.step === 'worktree' &&
|
|
196
196
|
ctx.state.modal.createWorktree
|
|
197
197
|
) {
|
|
198
|
-
return r([{ type: 'enter-new-tab-worktree-create' }])
|
|
198
|
+
return r([{ type: 'enter-new-tab-worktree-create' }], [{ type: 'load-new-tab-base-branches' }])
|
|
199
199
|
}
|
|
200
200
|
return r([], [{ type: 'launch-selected-assistant' }])
|
|
201
201
|
}
|
|
@@ -210,19 +210,49 @@ export const deleteSelectedWorktree: ActionFn = (ctx: ModeContext) => {
|
|
|
210
210
|
const session = ctx.state.sessions.find((entry) => entry.id === sessionId)
|
|
211
211
|
const worktree = session?.worktrees?.[modal.selectedIndex]
|
|
212
212
|
if (!worktree) return null
|
|
213
|
+
// First attempt is never forced — a recoverable failure opens the confirm
|
|
214
|
+
// dialog (see set-new-tab-worktree-delete-prompt), where confirmDeleteWorktree
|
|
215
|
+
// retries with force.
|
|
213
216
|
return r(
|
|
214
|
-
[
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
[{ index: modal.selectedIndex, type: 'set-modal-selection-index' }],
|
|
218
|
+
[{ force: false, sessionId, type: 'delete-worktree', worktreeId: worktree.id }]
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const confirmDeleteWorktree: ActionFn = (ctx: ModeContext) => {
|
|
223
|
+
const modal = ctx.state.modal
|
|
224
|
+
const sessionId = ctx.state.currentSessionId
|
|
225
|
+
if (modal.type !== 'new-tab' || modal.worktreeDeletePrompt == null) return null
|
|
226
|
+
if (!(sessionId != null && sessionId !== '')) return null
|
|
227
|
+
const { worktreeId } = modal.worktreeDeletePrompt
|
|
228
|
+
return r(
|
|
229
|
+
[{ prompt: null, type: 'set-new-tab-worktree-delete-prompt' }],
|
|
230
|
+
[{ force: true, sessionId, type: 'delete-worktree', worktreeId }],
|
|
231
|
+
'modal.new-tab.command-edit'
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export const cancelDeleteWorktree: KeyResult = r(
|
|
236
|
+
[{ prompt: null, type: 'set-new-tab-worktree-delete-prompt' }],
|
|
237
|
+
[],
|
|
238
|
+
'modal.new-tab.command-edit'
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
export const confirmWorktreeDeleteModal: ActionFn = (ctx: ModeContext) => {
|
|
242
|
+
const modal = ctx.state.modal
|
|
243
|
+
if (modal.type !== 'worktree-delete-confirm') return null
|
|
244
|
+
return r(
|
|
245
|
+
[{ type: 'close-modal' }],
|
|
218
246
|
[
|
|
219
247
|
{
|
|
220
|
-
|
|
221
|
-
|
|
248
|
+
closeTabs: modal.closeTabs,
|
|
249
|
+
force: modal.force,
|
|
250
|
+
sessionId: modal.sessionId,
|
|
222
251
|
type: 'delete-worktree',
|
|
223
|
-
worktreeId:
|
|
252
|
+
worktreeId: modal.worktreeId,
|
|
224
253
|
},
|
|
225
|
-
]
|
|
254
|
+
],
|
|
255
|
+
'navigation'
|
|
226
256
|
)
|
|
227
257
|
}
|
|
228
258
|
|
|
@@ -373,7 +403,10 @@ export const openWorktreeMove: ActionFn = (ctx: ModeContext) => {
|
|
|
373
403
|
}
|
|
374
404
|
// Overlay: no mode transition — deriveModeId routes input to the picker and
|
|
375
405
|
// focusMode stays 'git' so the git view remains mounted underneath.
|
|
376
|
-
return r(
|
|
406
|
+
return r(
|
|
407
|
+
[{ sourceWorktreeId: source.id, type: 'open-worktree-move-modal' }],
|
|
408
|
+
[{ type: 'load-worktree-move-stats' }]
|
|
409
|
+
)
|
|
377
410
|
}
|
|
378
411
|
|
|
379
412
|
export const toggleWorktreeMoveDelete: KeyResult = r([{ type: 'toggle-worktree-move-delete' }])
|
|
@@ -406,6 +439,27 @@ export const confirmWorktreeMove: ActionFn = (ctx: ModeContext) => {
|
|
|
406
439
|
)
|
|
407
440
|
}
|
|
408
441
|
|
|
442
|
+
// Confirms the dialog opened after a recoverable move failure: re-runs the
|
|
443
|
+
// move with the flag matching the failure (stash the target / keep conflicts).
|
|
444
|
+
export const confirmWorktreeMoveRetry: ActionFn = (ctx: ModeContext) => {
|
|
445
|
+
const modal = ctx.state.modal
|
|
446
|
+
if (modal.type !== 'worktree-move-confirm') return null
|
|
447
|
+
return r(
|
|
448
|
+
[{ type: 'close-modal' }],
|
|
449
|
+
[
|
|
450
|
+
{
|
|
451
|
+
deleteSource: modal.deleteSource,
|
|
452
|
+
sessionId: modal.sessionId,
|
|
453
|
+
sourceWorktreeId: modal.sourceWorktreeId,
|
|
454
|
+
targetWorktreeId: modal.targetWorktreeId,
|
|
455
|
+
type: 'move-worktree',
|
|
456
|
+
...(modal.variant === 'stash-target' ? { stashTarget: true } : { keepConflicts: true }),
|
|
457
|
+
},
|
|
458
|
+
],
|
|
459
|
+
'navigation'
|
|
460
|
+
)
|
|
461
|
+
}
|
|
462
|
+
|
|
409
463
|
export const closePane: ActionFn = (ctx: ModeContext) => {
|
|
410
464
|
const tabId = ctx.state.activeTabId
|
|
411
465
|
if (!(tabId != null && tabId !== '')) return null
|
package/src/defaults.ts
CHANGED
|
@@ -204,6 +204,28 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
204
204
|
.map('<CR>', actions.confirmWorktreeMove, 'Move')
|
|
205
205
|
)
|
|
206
206
|
|
|
207
|
+
// -----------------------------------------------------------------------
|
|
208
|
+
// Modal: worktree-move recoverable-failure confirmation (stash / conflicts)
|
|
209
|
+
// -----------------------------------------------------------------------
|
|
210
|
+
.mode('modal.worktree-move-confirm', (m) =>
|
|
211
|
+
m
|
|
212
|
+
.map('<Esc>', actions.closeModal, 'Cancel')
|
|
213
|
+
.map('n', actions.closeModal, 'Cancel')
|
|
214
|
+
.map('<CR>', actions.confirmWorktreeMoveRetry, 'Confirm')
|
|
215
|
+
.map('y', actions.confirmWorktreeMoveRetry, 'Confirm')
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
// -----------------------------------------------------------------------
|
|
219
|
+
// Modal: standalone worktree delete confirmation (sidebar "Remove worktree")
|
|
220
|
+
// -----------------------------------------------------------------------
|
|
221
|
+
.mode('modal.worktree-delete-confirm', (m) =>
|
|
222
|
+
m
|
|
223
|
+
.map('<Esc>', actions.closeModal, 'Cancel')
|
|
224
|
+
.map('n', actions.closeModal, 'Cancel')
|
|
225
|
+
.map('<CR>', actions.confirmWorktreeDeleteModal, 'Delete worktree')
|
|
226
|
+
.map('y', actions.confirmWorktreeDeleteModal, 'Delete worktree')
|
|
227
|
+
)
|
|
228
|
+
|
|
207
229
|
// -----------------------------------------------------------------------
|
|
208
230
|
// Modal: rename-tab
|
|
209
231
|
// -----------------------------------------------------------------------
|
|
@@ -239,6 +261,17 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
239
261
|
.passthrough()
|
|
240
262
|
)
|
|
241
263
|
|
|
264
|
+
// -----------------------------------------------------------------------
|
|
265
|
+
// Modal: new-tab worktree delete confirmation dialog
|
|
266
|
+
// -----------------------------------------------------------------------
|
|
267
|
+
.mode('modal.new-tab.worktree-delete-confirm', (m) =>
|
|
268
|
+
m
|
|
269
|
+
.map('<Esc>', actions.cancelDeleteWorktree, 'Cancel')
|
|
270
|
+
.map('n', actions.cancelDeleteWorktree, 'Cancel')
|
|
271
|
+
.map('<CR>', actions.confirmDeleteWorktree, 'Delete worktree')
|
|
272
|
+
.map('y', actions.confirmDeleteWorktree, 'Delete worktree')
|
|
273
|
+
)
|
|
274
|
+
|
|
242
275
|
// -----------------------------------------------------------------------
|
|
243
276
|
// Modal: session-picker (always in filter mode via Picker)
|
|
244
277
|
// -----------------------------------------------------------------------
|
package/src/types.ts
CHANGED
|
@@ -14,6 +14,8 @@ export type ModeId =
|
|
|
14
14
|
| 'git-mode'
|
|
15
15
|
| 'modal.new-tab.command-edit'
|
|
16
16
|
| 'modal.new-tab.editing-command'
|
|
17
|
+
| 'modal.new-tab.worktree-delete-confirm'
|
|
18
|
+
| 'modal.worktree-delete-confirm'
|
|
17
19
|
| 'modal.session-picker.filtering'
|
|
18
20
|
| 'modal.session-name'
|
|
19
21
|
| 'modal.create-session'
|
|
@@ -28,6 +30,7 @@ export type ModeId =
|
|
|
28
30
|
| 'modal.git-commit.generating'
|
|
29
31
|
| 'modal.update-available'
|
|
30
32
|
| 'modal.worktree-move'
|
|
33
|
+
| 'modal.worktree-move-confirm'
|
|
31
34
|
| 'modal.ai-usage'
|
|
32
35
|
|
|
33
36
|
// ─── Primitive app types ──────────────────────────────────────────────────────
|
|
@@ -296,16 +299,21 @@ export interface ModalClosed extends ModalBase {
|
|
|
296
299
|
export interface ModalNewTab extends ModalBase {
|
|
297
300
|
type: 'new-tab'
|
|
298
301
|
editingCommand: AssistantId | null
|
|
299
|
-
activeField: 'assistant' | 'branch-name' | 'target-worktree' | 'worktree-name'
|
|
302
|
+
activeField: 'assistant' | 'branch-name' | 'target-worktree' | 'worktree-name' | 'base'
|
|
300
303
|
branchError: string | null
|
|
301
304
|
branchName: string
|
|
302
305
|
createWorktree: boolean
|
|
303
306
|
selectedAssistantId: AssistantId | null
|
|
304
307
|
step: 'assistant' | 'worktree' | 'worktree-create' | 'template'
|
|
305
308
|
targetWorktreeIndex: number
|
|
306
|
-
|
|
307
|
-
worktreeDeleteMessage: string | null
|
|
309
|
+
worktreeDeletePrompt: { worktreeId: string; reason: string } | null
|
|
308
310
|
worktreeName: string
|
|
311
|
+
/** Filter text typed into the "Base" picker on the worktree-create step. */
|
|
312
|
+
baseQuery: string
|
|
313
|
+
/** Resolved base ref the new worktree is forked from (branch of a worktree or a local branch). */
|
|
314
|
+
baseRef: string
|
|
315
|
+
/** Local branches available as base refs, loaded when the create step opens. */
|
|
316
|
+
baseBranches: string[]
|
|
309
317
|
}
|
|
310
318
|
export interface ModalSessionPicker extends ModalBase {
|
|
311
319
|
type: 'session-picker'
|
|
@@ -371,6 +379,42 @@ export interface ModalWorktreeMove extends ModalBase {
|
|
|
371
379
|
/** The worktree being moved (may differ from the active one, e.g. a tab menu). */
|
|
372
380
|
sourceWorktreeId: string
|
|
373
381
|
deleteSource: boolean
|
|
382
|
+
/** Per-worktree dirty file counts, loaded async when the modal opens. */
|
|
383
|
+
stats: { kind: 'loading' } | { kind: 'ready'; dirtyFiles: Record<string, number> }
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Confirmation for a recoverable move failure: the target's dirty files
|
|
388
|
+
* overlap the incoming changes (stash-target) or the squash conflicts
|
|
389
|
+
* (keep-conflicts). Both worktrees are already restored; confirming re-runs
|
|
390
|
+
* move-worktree with the matching flag.
|
|
391
|
+
*/
|
|
392
|
+
export interface ModalWorktreeMoveConfirm extends ModalBase {
|
|
393
|
+
type: 'worktree-move-confirm'
|
|
394
|
+
variant: 'stash-target' | 'keep-conflicts'
|
|
395
|
+
files: string[]
|
|
396
|
+
sessionId: string
|
|
397
|
+
sourceWorktreeId: string
|
|
398
|
+
targetWorktreeId: string
|
|
399
|
+
deleteSource: boolean
|
|
400
|
+
sourceLabel: string
|
|
401
|
+
targetLabel: string
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Standalone confirmation for a recoverable worktree delete failure triggered
|
|
406
|
+
* outside the new-tab picker (e.g. the sidebar's "Remove worktree"). Carries the
|
|
407
|
+
* params needed to re-run the delete with force once confirmed.
|
|
408
|
+
*/
|
|
409
|
+
export interface ModalWorktreeDeleteConfirm extends ModalBase {
|
|
410
|
+
type: 'worktree-delete-confirm'
|
|
411
|
+
sessionId: string
|
|
412
|
+
worktreeId: string
|
|
413
|
+
worktreeLabel: string
|
|
414
|
+
reason: string
|
|
415
|
+
closeTabs: boolean
|
|
416
|
+
/** Whether confirming force-deletes — true only after a recoverable failure. */
|
|
417
|
+
force: boolean
|
|
374
418
|
}
|
|
375
419
|
|
|
376
420
|
export type ModalState =
|
|
@@ -389,6 +433,8 @@ export type ModalState =
|
|
|
389
433
|
| ModalUpdateAvailable
|
|
390
434
|
| ModalAIUsage
|
|
391
435
|
| ModalWorktreeMove
|
|
436
|
+
| ModalWorktreeMoveConfirm
|
|
437
|
+
| ModalWorktreeDeleteConfirm
|
|
392
438
|
|
|
393
439
|
export interface LayoutState {
|
|
394
440
|
terminalCols: number
|
|
@@ -464,10 +510,10 @@ export type ModalAction =
|
|
|
464
510
|
| { type: 'open-new-tab-modal' }
|
|
465
511
|
| { type: 'set-new-tab-branch-error'; message: string | null }
|
|
466
512
|
| {
|
|
467
|
-
type: 'set-new-tab-worktree-delete-
|
|
468
|
-
|
|
469
|
-
message: string | null
|
|
513
|
+
type: 'set-new-tab-worktree-delete-prompt'
|
|
514
|
+
prompt: { worktreeId: string; reason: string } | null
|
|
470
515
|
}
|
|
516
|
+
| { type: 'set-new-tab-base-branches'; branches: string[] }
|
|
471
517
|
| { type: 'enter-new-tab-worktree-create' }
|
|
472
518
|
| { type: 'enter-new-tab-template-pick' }
|
|
473
519
|
| { type: 'enter-new-tab-template-shortcut' }
|
|
@@ -502,6 +548,27 @@ export type ModalAction =
|
|
|
502
548
|
| { type: 'open-edit-custom-command'; assistantId: AssistantId }
|
|
503
549
|
| { type: 'open-worktree-move-modal'; sourceWorktreeId: string }
|
|
504
550
|
| { type: 'toggle-worktree-move-delete' }
|
|
551
|
+
| { type: 'set-worktree-move-stats'; dirtyFiles: Record<string, number> }
|
|
552
|
+
| {
|
|
553
|
+
type: 'open-worktree-move-confirm'
|
|
554
|
+
variant: 'stash-target' | 'keep-conflicts'
|
|
555
|
+
files: string[]
|
|
556
|
+
sessionId: string
|
|
557
|
+
sourceWorktreeId: string
|
|
558
|
+
targetWorktreeId: string
|
|
559
|
+
deleteSource: boolean
|
|
560
|
+
sourceLabel: string
|
|
561
|
+
targetLabel: string
|
|
562
|
+
}
|
|
563
|
+
| {
|
|
564
|
+
type: 'open-worktree-delete-confirm'
|
|
565
|
+
sessionId: string
|
|
566
|
+
worktreeId: string
|
|
567
|
+
worktreeLabel: string
|
|
568
|
+
reason: string
|
|
569
|
+
closeTabs: boolean
|
|
570
|
+
force: boolean
|
|
571
|
+
}
|
|
505
572
|
|
|
506
573
|
export type SessionAction =
|
|
507
574
|
| { type: 'load-session'; sessionId: string; workspaceSnapshot?: WorkspaceSnapshotV1 }
|
|
@@ -513,7 +580,6 @@ export type SessionAction =
|
|
|
513
580
|
| { type: 'reorder-active-session'; delta: number }
|
|
514
581
|
| { type: 'set-session-status'; sessionId: string; status: SessionStatus }
|
|
515
582
|
| { type: 'add-worktree-record'; sessionId: string; worktree: WorktreeRecord; activate?: boolean }
|
|
516
|
-
| { type: 'remove-worktree-record'; sessionId: string; worktreeId: string }
|
|
517
583
|
| { type: 'set-active-worktree'; sessionId: string; worktreeId: string }
|
|
518
584
|
| {
|
|
519
585
|
type: 'update-worktree-record'
|
|
@@ -709,6 +775,7 @@ export type AppAction =
|
|
|
709
775
|
export type SideEffect =
|
|
710
776
|
| { type: 'quit'; state: AppState }
|
|
711
777
|
| { type: 'launch-selected-assistant' }
|
|
778
|
+
| { type: 'load-new-tab-base-branches' }
|
|
712
779
|
| { type: 'edit-selected-assistant' }
|
|
713
780
|
| { type: 'confirm-selected-session' }
|
|
714
781
|
| { type: 'delete-selected-session' }
|
|
@@ -748,14 +815,29 @@ export type SideEffect =
|
|
|
748
815
|
| { type: 'cycle-sidebar-item'; direction: 1 | -1 }
|
|
749
816
|
| { type: 'switch-tab-by-index'; index: number }
|
|
750
817
|
| { type: 'delete-session'; sessionId: string }
|
|
751
|
-
| {
|
|
818
|
+
| {
|
|
819
|
+
type: 'delete-worktree'
|
|
820
|
+
sessionId: string
|
|
821
|
+
worktreeId: string
|
|
822
|
+
// Force the git worktree removal (discards uncommitted changes in the
|
|
823
|
+
// worktree). Also implies closing the worktree's tabs.
|
|
824
|
+
force?: boolean
|
|
825
|
+
// Close the worktree's tabs without forcing the git removal. Lets the
|
|
826
|
+
// sidebar "Remove worktree" clean up tabs (avoiding orphans) while still
|
|
827
|
+
// refusing to discard uncommitted work in a temp worktree.
|
|
828
|
+
closeTabs?: boolean
|
|
829
|
+
}
|
|
752
830
|
| {
|
|
753
831
|
type: 'move-worktree'
|
|
754
832
|
sessionId: string
|
|
755
833
|
sourceWorktreeId: string
|
|
756
834
|
targetWorktreeId: string
|
|
757
835
|
deleteSource?: boolean
|
|
836
|
+
// Retry flags set by the worktree-move-confirm dialog.
|
|
837
|
+
stashTarget?: boolean
|
|
838
|
+
keepConflicts?: boolean
|
|
758
839
|
}
|
|
840
|
+
| { type: 'load-worktree-move-stats' }
|
|
759
841
|
| { type: 'toggle-transparent' }
|
|
760
842
|
| { type: 'toggle-mode' }
|
|
761
843
|
| { type: 'open-file-in-editor'; path: string }
|