@brimveyn/aimux-config 0.6.8 → 0.6.10
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 +39 -9
- package/src/defaults.ts +22 -0
- package/src/index.ts +3 -0
- package/src/resolver.ts +1 -0
- package/src/types.ts +90 -9
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
|
|
package/src/defaults.ts
CHANGED
|
@@ -204,6 +204,17 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
204
204
|
.map('<CR>', actions.confirmWorktreeMove, 'Move')
|
|
205
205
|
)
|
|
206
206
|
|
|
207
|
+
// -----------------------------------------------------------------------
|
|
208
|
+
// Modal: standalone worktree delete confirmation (sidebar "Remove worktree")
|
|
209
|
+
// -----------------------------------------------------------------------
|
|
210
|
+
.mode('modal.worktree-delete-confirm', (m) =>
|
|
211
|
+
m
|
|
212
|
+
.map('<Esc>', actions.closeModal, 'Cancel')
|
|
213
|
+
.map('n', actions.closeModal, 'Cancel')
|
|
214
|
+
.map('<CR>', actions.confirmWorktreeDeleteModal, 'Delete worktree')
|
|
215
|
+
.map('y', actions.confirmWorktreeDeleteModal, 'Delete worktree')
|
|
216
|
+
)
|
|
217
|
+
|
|
207
218
|
// -----------------------------------------------------------------------
|
|
208
219
|
// Modal: rename-tab
|
|
209
220
|
// -----------------------------------------------------------------------
|
|
@@ -239,6 +250,17 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
|
|
|
239
250
|
.passthrough()
|
|
240
251
|
)
|
|
241
252
|
|
|
253
|
+
// -----------------------------------------------------------------------
|
|
254
|
+
// Modal: new-tab worktree delete confirmation dialog
|
|
255
|
+
// -----------------------------------------------------------------------
|
|
256
|
+
.mode('modal.new-tab.worktree-delete-confirm', (m) =>
|
|
257
|
+
m
|
|
258
|
+
.map('<Esc>', actions.cancelDeleteWorktree, 'Cancel')
|
|
259
|
+
.map('n', actions.cancelDeleteWorktree, 'Cancel')
|
|
260
|
+
.map('<CR>', actions.confirmDeleteWorktree, 'Delete worktree')
|
|
261
|
+
.map('y', actions.confirmDeleteWorktree, 'Delete worktree')
|
|
262
|
+
)
|
|
263
|
+
|
|
242
264
|
// -----------------------------------------------------------------------
|
|
243
265
|
// Modal: session-picker (always in filter mode via Picker)
|
|
244
266
|
// -----------------------------------------------------------------------
|
package/src/index.ts
CHANGED
package/src/resolver.ts
CHANGED
|
@@ -48,6 +48,7 @@ export function resolveConfig(userConfig: AimuxUserConfig): ResolvedConfig {
|
|
|
48
48
|
snippetTriggerChar: resolveSnippetTriggerChar(userConfig.snippetTriggerChar),
|
|
49
49
|
statusBar: userConfig.statusBar ?? {},
|
|
50
50
|
theme: resolveTheme(userConfig.theme),
|
|
51
|
+
worktreeTemplates: userConfig.worktreeTemplates ?? [],
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
|
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'
|
|
@@ -124,6 +126,13 @@ export interface WorkspaceSnapshotV1 {
|
|
|
124
126
|
layoutTree?: LayoutNode
|
|
125
127
|
layoutTrees?: Record<string, LayoutNode>
|
|
126
128
|
tabGroupMap?: Record<string, string>
|
|
129
|
+
/**
|
|
130
|
+
* Last viewed tab per worktree, keyed by worktree id. Optional and additive
|
|
131
|
+
* (no version bump): older builds ignore it, newer builds tolerate its
|
|
132
|
+
* absence. Written now so the data accrues, but restoring it at startup is
|
|
133
|
+
* gated off until a future change flips RESTORE_LAST_ACTIVE_TAB_BY_WORKTREE.
|
|
134
|
+
*/
|
|
135
|
+
lastActiveTabByWorktree?: Record<string, string>
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
export type WorktreeSource = 'primary' | 'aimux-temp' | 'external'
|
|
@@ -289,16 +298,21 @@ export interface ModalClosed extends ModalBase {
|
|
|
289
298
|
export interface ModalNewTab extends ModalBase {
|
|
290
299
|
type: 'new-tab'
|
|
291
300
|
editingCommand: AssistantId | null
|
|
292
|
-
activeField: 'assistant' | 'branch-name' | 'target-worktree' | 'worktree-name'
|
|
301
|
+
activeField: 'assistant' | 'branch-name' | 'target-worktree' | 'worktree-name' | 'base'
|
|
293
302
|
branchError: string | null
|
|
294
303
|
branchName: string
|
|
295
304
|
createWorktree: boolean
|
|
296
305
|
selectedAssistantId: AssistantId | null
|
|
297
|
-
step: 'assistant' | 'worktree' | 'worktree-create'
|
|
306
|
+
step: 'assistant' | 'worktree' | 'worktree-create' | 'template'
|
|
298
307
|
targetWorktreeIndex: number
|
|
299
|
-
|
|
300
|
-
worktreeDeleteMessage: string | null
|
|
308
|
+
worktreeDeletePrompt: { worktreeId: string; reason: string } | null
|
|
301
309
|
worktreeName: string
|
|
310
|
+
/** Filter text typed into the "Base" picker on the worktree-create step. */
|
|
311
|
+
baseQuery: string
|
|
312
|
+
/** Resolved base ref the new worktree is forked from (branch of a worktree or a local branch). */
|
|
313
|
+
baseRef: string
|
|
314
|
+
/** Local branches available as base refs, loaded when the create step opens. */
|
|
315
|
+
baseBranches: string[]
|
|
302
316
|
}
|
|
303
317
|
export interface ModalSessionPicker extends ModalBase {
|
|
304
318
|
type: 'session-picker'
|
|
@@ -366,6 +380,22 @@ export interface ModalWorktreeMove extends ModalBase {
|
|
|
366
380
|
deleteSource: boolean
|
|
367
381
|
}
|
|
368
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Standalone confirmation for a recoverable worktree delete failure triggered
|
|
385
|
+
* outside the new-tab picker (e.g. the sidebar's "Remove worktree"). Carries the
|
|
386
|
+
* params needed to re-run the delete with force once confirmed.
|
|
387
|
+
*/
|
|
388
|
+
export interface ModalWorktreeDeleteConfirm extends ModalBase {
|
|
389
|
+
type: 'worktree-delete-confirm'
|
|
390
|
+
sessionId: string
|
|
391
|
+
worktreeId: string
|
|
392
|
+
worktreeLabel: string
|
|
393
|
+
reason: string
|
|
394
|
+
closeTabs: boolean
|
|
395
|
+
/** Whether confirming force-deletes — true only after a recoverable failure. */
|
|
396
|
+
force: boolean
|
|
397
|
+
}
|
|
398
|
+
|
|
369
399
|
export type ModalState =
|
|
370
400
|
| ModalClosed
|
|
371
401
|
| ModalNewTab
|
|
@@ -382,6 +412,7 @@ export type ModalState =
|
|
|
382
412
|
| ModalUpdateAvailable
|
|
383
413
|
| ModalAIUsage
|
|
384
414
|
| ModalWorktreeMove
|
|
415
|
+
| ModalWorktreeDeleteConfirm
|
|
385
416
|
|
|
386
417
|
export interface LayoutState {
|
|
387
418
|
terminalCols: number
|
|
@@ -446,7 +477,9 @@ export interface AppState {
|
|
|
446
477
|
autoCommit: AutoCommitState
|
|
447
478
|
multiRepo: MultiRepoState
|
|
448
479
|
worktreeDivergence: Record<string, BranchDivergence>
|
|
480
|
+
lastActiveTabByWorktree: Record<string, string>
|
|
449
481
|
pendingChords: string[] | null
|
|
482
|
+
worktreeTemplates: WorktreeTemplate[]
|
|
450
483
|
}
|
|
451
484
|
|
|
452
485
|
// ─── AppAction union ──────────────────────────────────────────────────────────
|
|
@@ -455,11 +488,13 @@ export type ModalAction =
|
|
|
455
488
|
| { type: 'open-new-tab-modal' }
|
|
456
489
|
| { type: 'set-new-tab-branch-error'; message: string | null }
|
|
457
490
|
| {
|
|
458
|
-
type: 'set-new-tab-worktree-delete-
|
|
459
|
-
|
|
460
|
-
message: string | null
|
|
491
|
+
type: 'set-new-tab-worktree-delete-prompt'
|
|
492
|
+
prompt: { worktreeId: string; reason: string } | null
|
|
461
493
|
}
|
|
494
|
+
| { type: 'set-new-tab-base-branches'; branches: string[] }
|
|
462
495
|
| { type: 'enter-new-tab-worktree-create' }
|
|
496
|
+
| { type: 'enter-new-tab-template-pick' }
|
|
497
|
+
| { type: 'enter-new-tab-template-shortcut' }
|
|
463
498
|
| { type: 'select-new-tab-assistant'; assistantId?: AssistantId }
|
|
464
499
|
| { type: 'toggle-new-tab-worktree'; assistantId?: AssistantId }
|
|
465
500
|
| { type: 'open-help-modal'; scope?: ModeId }
|
|
@@ -491,6 +526,15 @@ export type ModalAction =
|
|
|
491
526
|
| { type: 'open-edit-custom-command'; assistantId: AssistantId }
|
|
492
527
|
| { type: 'open-worktree-move-modal'; sourceWorktreeId: string }
|
|
493
528
|
| { type: 'toggle-worktree-move-delete' }
|
|
529
|
+
| {
|
|
530
|
+
type: 'open-worktree-delete-confirm'
|
|
531
|
+
sessionId: string
|
|
532
|
+
worktreeId: string
|
|
533
|
+
worktreeLabel: string
|
|
534
|
+
reason: string
|
|
535
|
+
closeTabs: boolean
|
|
536
|
+
force: boolean
|
|
537
|
+
}
|
|
494
538
|
|
|
495
539
|
export type SessionAction =
|
|
496
540
|
| { type: 'load-session'; sessionId: string; workspaceSnapshot?: WorkspaceSnapshotV1 }
|
|
@@ -502,7 +546,6 @@ export type SessionAction =
|
|
|
502
546
|
| { type: 'reorder-active-session'; delta: number }
|
|
503
547
|
| { type: 'set-session-status'; sessionId: string; status: SessionStatus }
|
|
504
548
|
| { type: 'add-worktree-record'; sessionId: string; worktree: WorktreeRecord; activate?: boolean }
|
|
505
|
-
| { type: 'remove-worktree-record'; sessionId: string; worktreeId: string }
|
|
506
549
|
| { type: 'set-active-worktree'; sessionId: string; worktreeId: string }
|
|
507
550
|
| {
|
|
508
551
|
type: 'update-worktree-record'
|
|
@@ -590,6 +633,26 @@ export interface BranchDivergence {
|
|
|
590
633
|
behind: number
|
|
591
634
|
}
|
|
592
635
|
|
|
636
|
+
export interface WorktreeTemplatePane {
|
|
637
|
+
id: string
|
|
638
|
+
assistant: string
|
|
639
|
+
splitFrom?: string
|
|
640
|
+
direction?: SplitDirection
|
|
641
|
+
ratio?: number
|
|
642
|
+
send?: string
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export interface WorktreeTemplateTab {
|
|
646
|
+
panes: WorktreeTemplatePane[]
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
export interface WorktreeTemplate {
|
|
650
|
+
id: string
|
|
651
|
+
name: string
|
|
652
|
+
description?: string
|
|
653
|
+
tabs: WorktreeTemplateTab[]
|
|
654
|
+
}
|
|
655
|
+
|
|
593
656
|
export type GitPanelAction =
|
|
594
657
|
| { type: 'git-refresh-success'; payload: GitRefreshPayload }
|
|
595
658
|
| { type: 'git-refresh-error'; kind: GitPanelError }
|
|
@@ -678,6 +741,7 @@ export type AppAction =
|
|
|
678
741
|
export type SideEffect =
|
|
679
742
|
| { type: 'quit'; state: AppState }
|
|
680
743
|
| { type: 'launch-selected-assistant' }
|
|
744
|
+
| { type: 'load-new-tab-base-branches' }
|
|
681
745
|
| { type: 'edit-selected-assistant' }
|
|
682
746
|
| { type: 'confirm-selected-session' }
|
|
683
747
|
| { type: 'delete-selected-session' }
|
|
@@ -717,7 +781,18 @@ export type SideEffect =
|
|
|
717
781
|
| { type: 'cycle-sidebar-item'; direction: 1 | -1 }
|
|
718
782
|
| { type: 'switch-tab-by-index'; index: number }
|
|
719
783
|
| { type: 'delete-session'; sessionId: string }
|
|
720
|
-
| {
|
|
784
|
+
| {
|
|
785
|
+
type: 'delete-worktree'
|
|
786
|
+
sessionId: string
|
|
787
|
+
worktreeId: string
|
|
788
|
+
// Force the git worktree removal (discards uncommitted changes in the
|
|
789
|
+
// worktree). Also implies closing the worktree's tabs.
|
|
790
|
+
force?: boolean
|
|
791
|
+
// Close the worktree's tabs without forcing the git removal. Lets the
|
|
792
|
+
// sidebar "Remove worktree" clean up tabs (avoiding orphans) while still
|
|
793
|
+
// refusing to discard uncommitted work in a temp worktree.
|
|
794
|
+
closeTabs?: boolean
|
|
795
|
+
}
|
|
721
796
|
| {
|
|
722
797
|
type: 'move-worktree'
|
|
723
798
|
sessionId: string
|
|
@@ -1038,6 +1113,11 @@ export interface AimuxUserConfig {
|
|
|
1038
1113
|
statusBar?: StatusBarConfig
|
|
1039
1114
|
externalEditor?: ExternalEditorConfig
|
|
1040
1115
|
integrations?: AimuxIntegrationsConfig
|
|
1116
|
+
/**
|
|
1117
|
+
* Worktree templates: layouts (multi-pane + initial commands) applied at
|
|
1118
|
+
* worktree creation. Selected from a picker in the new-tab modal.
|
|
1119
|
+
*/
|
|
1120
|
+
worktreeTemplates?: WorktreeTemplate[]
|
|
1041
1121
|
}
|
|
1042
1122
|
|
|
1043
1123
|
// ─── Resolved config (internal) ───────────────────────────────────────────────
|
|
@@ -1114,4 +1194,5 @@ export interface ResolvedConfig {
|
|
|
1114
1194
|
integrations: {
|
|
1115
1195
|
claudeHooks: boolean
|
|
1116
1196
|
}
|
|
1197
|
+
worktreeTemplates: WorktreeTemplate[]
|
|
1117
1198
|
}
|