@brimveyn/aimux 1.16.0 → 1.16.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.
- package/package.json +1 -1
- package/src/app-runtime/side-effects.ts +14 -8
- package/src/input/keymap/help-entries.ts +1 -0
- package/src/input/modes/bridge.ts +1 -0
- package/src/input/modes/transitions.ts +2 -0
- package/src/input/modes/types.ts +1 -0
- package/src/state/reducers/modal-state.ts +14 -0
- package/src/state/types.ts +13 -0
- package/src/ui/components/layout/sidebar/worktree-row.tsx +16 -4
- package/src/ui/root.tsx +2 -0
- package/src/ui/status-bar-model.ts +2 -0
package/package.json
CHANGED
|
@@ -1610,7 +1610,6 @@ async function runDeleteWorktree(
|
|
|
1610
1610
|
if (tabsInWorktree.length > 0 && !force && !closeTabs) {
|
|
1611
1611
|
throw new ActiveWorktreeTabsError(tabsInWorktree.length)
|
|
1612
1612
|
}
|
|
1613
|
-
disposeWorktreeTabs(ctx, worktreeId)
|
|
1614
1613
|
|
|
1615
1614
|
const repoPath = resolveWorktreeGitDir(session, worktree)
|
|
1616
1615
|
const isAimuxTemp = worktree.source === 'aimux-temp' && worktree.createdByAimux
|
|
@@ -1624,15 +1623,14 @@ async function runDeleteWorktree(
|
|
|
1624
1623
|
}
|
|
1625
1624
|
}
|
|
1626
1625
|
|
|
1626
|
+
// Run git ops FIRST. If any throws (dirty worktree, etc.) the catch in the
|
|
1627
|
+
// delete-worktree side effect handler re-prompts force or toasts the error —
|
|
1628
|
+
// tabs stay open and the row stays in the sidebar, so the UI matches reality
|
|
1629
|
+
// instead of leaving tabs closed against a worktree that still exists.
|
|
1627
1630
|
if (isAimuxTemp && isInsideAimuxWorktreeRoot(worktree.path) && !existsSync(worktree.path)) {
|
|
1628
1631
|
// The dir vanished but git may still pin the branch to a stale worktree entry.
|
|
1629
1632
|
await pruneGitWorktrees(repoPath)
|
|
1630
|
-
|
|
1631
|
-
removeWorktreeRecordFromSession(ctx, sessionId, session, worktreeId)
|
|
1632
|
-
return
|
|
1633
|
-
}
|
|
1634
|
-
|
|
1635
|
-
if (isAimuxTemp && isInsideAimuxWorktreeRoot(worktree.path)) {
|
|
1633
|
+
} else if (isAimuxTemp && isInsideAimuxWorktreeRoot(worktree.path)) {
|
|
1636
1634
|
await assertSafeAimuxWorktreePath(worktree.path)
|
|
1637
1635
|
await removeGitWorktree({ force, repoPath, targetPath: worktree.path })
|
|
1638
1636
|
} else if (worktree.source === 'aimux-temp' || worktree.createdByAimux) {
|
|
@@ -1640,7 +1638,15 @@ async function runDeleteWorktree(
|
|
|
1640
1638
|
}
|
|
1641
1639
|
|
|
1642
1640
|
await cleanupAimuxBranch()
|
|
1643
|
-
|
|
1641
|
+
|
|
1642
|
+
// Only after git success: close tabs + retire the record. Re-read state so
|
|
1643
|
+
// we don't operate on the snapshot captured before the awaits above.
|
|
1644
|
+
disposeWorktreeTabs({ ...ctx, state: ctx.getState() }, worktreeId)
|
|
1645
|
+
const latest = ctx.getState()
|
|
1646
|
+
const latestSession = latest.sessions.find((entry) => entry.id === sessionId)
|
|
1647
|
+
if (latestSession) {
|
|
1648
|
+
removeWorktreeRecordFromSession({ ...ctx, state: latest }, sessionId, latestSession, worktreeId)
|
|
1649
|
+
}
|
|
1644
1650
|
}
|
|
1645
1651
|
|
|
1646
1652
|
// A worktree's stored repoRoot can point at a sibling worktree that was since
|
|
@@ -19,6 +19,7 @@ export const HELP_MODE_LABELS: { modeId: ModeId; label: string }[] = [
|
|
|
19
19
|
{ label: 'Workspace name', modeId: 'modal.session-name' },
|
|
20
20
|
{ label: 'Create workspace', modeId: 'modal.create-session' },
|
|
21
21
|
{ label: 'Rename tab', modeId: 'modal.rename-tab' },
|
|
22
|
+
{ label: 'Rename worktree', modeId: 'modal.rename-worktree' },
|
|
22
23
|
{ label: 'Snippet picker', modeId: 'modal.snippet-picker.filtering' },
|
|
23
24
|
{ label: 'Snippet picker — filter', modeId: 'modal.snippet-picker.filtering' },
|
|
24
25
|
{ label: 'Snippet editor', modeId: 'modal.snippet-editor' },
|
|
@@ -15,6 +15,7 @@ const COMMAND_EDIT_MODE_IDS: Partial<Record<SupportedModalType, ModeId>> = {
|
|
|
15
15
|
'help': 'modal.help.filtering',
|
|
16
16
|
'new-tab': 'modal.new-tab.command-edit',
|
|
17
17
|
'rename-tab': 'modal.rename-tab',
|
|
18
|
+
'rename-worktree': 'modal.rename-worktree',
|
|
18
19
|
'session-name': 'modal.session-name',
|
|
19
20
|
'session-picker': 'modal.session-picker.filtering',
|
|
20
21
|
'snippet-editor': 'modal.snippet-editor',
|
|
@@ -16,6 +16,7 @@ const TRANSITIONS: Record<ModeId, readonly ModeId[]> = {
|
|
|
16
16
|
'modal.new-tab.editing-command': ['navigation', 'modal.new-tab.command-edit'],
|
|
17
17
|
'modal.new-tab.worktree-delete-confirm': ['navigation', 'modal.new-tab.command-edit'],
|
|
18
18
|
'modal.rename-tab': ['navigation'],
|
|
19
|
+
'modal.rename-worktree': ['navigation'],
|
|
19
20
|
'modal.session-name': ['modal.session-picker.filtering', 'navigation'],
|
|
20
21
|
'modal.session-picker.filtering': ['navigation', 'modal.session-name', 'modal.create-session'],
|
|
21
22
|
'modal.snippet-editor': ['navigation', 'modal.snippet-picker.filtering'],
|
|
@@ -35,6 +36,7 @@ const TRANSITIONS: Record<ModeId, readonly ModeId[]> = {
|
|
|
35
36
|
'modal.snippet-picker.filtering',
|
|
36
37
|
'modal.theme-picker.filtering',
|
|
37
38
|
'modal.rename-tab',
|
|
39
|
+
'modal.rename-worktree',
|
|
38
40
|
'modal.update-available',
|
|
39
41
|
'modal.ai-usage',
|
|
40
42
|
'modal.worktree-delete-confirm',
|
package/src/input/modes/types.ts
CHANGED
|
@@ -1217,6 +1217,20 @@ export function reduceModalState(state: AppState, action: AppAction): AppState |
|
|
|
1217
1217
|
},
|
|
1218
1218
|
}
|
|
1219
1219
|
}
|
|
1220
|
+
case 'open-rename-worktree-modal': {
|
|
1221
|
+
return {
|
|
1222
|
+
...state,
|
|
1223
|
+
focusMode: 'command-edit',
|
|
1224
|
+
modal: {
|
|
1225
|
+
cursorPos: action.initialName.length,
|
|
1226
|
+
editBuffer: action.initialName,
|
|
1227
|
+
selectedIndex: 0,
|
|
1228
|
+
sessionTargetId: action.worktreeId,
|
|
1229
|
+
type: 'rename-worktree',
|
|
1230
|
+
worktreeSessionId: action.sessionId,
|
|
1231
|
+
},
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1220
1234
|
default:
|
|
1221
1235
|
return null
|
|
1222
1236
|
}
|
package/src/state/types.ts
CHANGED
|
@@ -38,6 +38,7 @@ export type ModalType =
|
|
|
38
38
|
| 'session-name'
|
|
39
39
|
| 'create-session'
|
|
40
40
|
| 'rename-tab'
|
|
41
|
+
| 'rename-worktree'
|
|
41
42
|
| 'snippet-picker'
|
|
42
43
|
| 'snippet-editor'
|
|
43
44
|
| 'theme-picker'
|
|
@@ -365,6 +366,11 @@ export interface ModalRenameTab extends ModalBase {
|
|
|
365
366
|
type: 'rename-tab'
|
|
366
367
|
}
|
|
367
368
|
|
|
369
|
+
export interface ModalRenameWorktree extends ModalBase {
|
|
370
|
+
type: 'rename-worktree'
|
|
371
|
+
worktreeSessionId: string
|
|
372
|
+
}
|
|
373
|
+
|
|
368
374
|
export interface ModalSnippetPicker extends ModalBase {
|
|
369
375
|
type: 'snippet-picker'
|
|
370
376
|
/**
|
|
@@ -483,6 +489,7 @@ export type ModalState =
|
|
|
483
489
|
| ModalSessionPicker
|
|
484
490
|
| ModalSessionName
|
|
485
491
|
| ModalRenameTab
|
|
492
|
+
| ModalRenameWorktree
|
|
486
493
|
| ModalSnippetPicker
|
|
487
494
|
| ModalThemePicker
|
|
488
495
|
| ModalHelp
|
|
@@ -598,6 +605,12 @@ export type ModalAction =
|
|
|
598
605
|
| { type: 'switch-create-session-field' }
|
|
599
606
|
| { type: 'select-directory' }
|
|
600
607
|
| { type: 'open-rename-tab-modal' }
|
|
608
|
+
| {
|
|
609
|
+
type: 'open-rename-worktree-modal'
|
|
610
|
+
sessionId: string
|
|
611
|
+
worktreeId: string
|
|
612
|
+
initialName: string
|
|
613
|
+
}
|
|
601
614
|
| { type: 'open-snippet-picker' }
|
|
602
615
|
| { type: 'open-snippet-editor'; snippetId?: string }
|
|
603
616
|
| { type: 'set-help-entry-count'; count: number }
|
|
@@ -63,9 +63,20 @@ export const WorktreeRow = memo(function WorktreeRow({
|
|
|
63
63
|
)
|
|
64
64
|
|
|
65
65
|
const rightClickMenu = useMemo<[string, () => void][] | undefined>(() => {
|
|
66
|
-
|
|
67
|
-
return [
|
|
66
|
+
const entries: [string, () => void][] = [
|
|
68
67
|
[
|
|
68
|
+
'Rename',
|
|
69
|
+
() =>
|
|
70
|
+
dispatchGlobal({
|
|
71
|
+
initialName: worktree.name,
|
|
72
|
+
sessionId: session.id,
|
|
73
|
+
type: 'open-rename-worktree-modal',
|
|
74
|
+
worktreeId: worktree.id,
|
|
75
|
+
}),
|
|
76
|
+
],
|
|
77
|
+
]
|
|
78
|
+
if (worktree.source !== 'primary') {
|
|
79
|
+
entries.push([
|
|
69
80
|
'Remove worktree',
|
|
70
81
|
() =>
|
|
71
82
|
// Always confirm first. Confirming routes through the full delete side
|
|
@@ -83,8 +94,9 @@ export const WorktreeRow = memo(function WorktreeRow({
|
|
|
83
94
|
worktreeId: worktree.id,
|
|
84
95
|
worktreeLabel: worktree.branch ?? worktree.name,
|
|
85
96
|
}),
|
|
86
|
-
]
|
|
87
|
-
|
|
97
|
+
])
|
|
98
|
+
}
|
|
99
|
+
return entries
|
|
88
100
|
}, [session.id, worktree.branch, worktree.id, worktree.name, worktree.source])
|
|
89
101
|
|
|
90
102
|
let bgColor: string | undefined
|
package/src/ui/root.tsx
CHANGED
|
@@ -156,6 +156,8 @@ function renderModal(
|
|
|
156
156
|
)
|
|
157
157
|
case 'rename-tab':
|
|
158
158
|
return <SessionNameModal title="Rename tab" value={modal.editBuffer ?? ''} />
|
|
159
|
+
case 'rename-worktree':
|
|
160
|
+
return <SessionNameModal title="Rename worktree" value={modal.editBuffer ?? ''} />
|
|
159
161
|
case 'create-session':
|
|
160
162
|
return (
|
|
161
163
|
<CreateSessionModal
|
|
@@ -150,6 +150,8 @@ function deriveCommandEditModeId(modalType: AppState['modal']['type']): ModeId |
|
|
|
150
150
|
return 'modal.new-tab.command-edit'
|
|
151
151
|
case 'rename-tab':
|
|
152
152
|
return 'modal.rename-tab'
|
|
153
|
+
case 'rename-worktree':
|
|
154
|
+
return 'modal.rename-worktree'
|
|
153
155
|
case 'session-name':
|
|
154
156
|
return 'modal.session-name'
|
|
155
157
|
case 'session-picker':
|