@brimveyn/aimux 1.21.0 → 1.22.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/README.md +27 -25
- package/package.json +2 -2
- package/src/app-runtime/auto-commit-driver.ts +22 -27
- package/src/app-runtime/backend-attach-runtime.ts +43 -36
- package/src/app-runtime/backend-runtime-events.ts +107 -88
- package/src/app-runtime/editor-actions.ts +201 -0
- package/src/app-runtime/git-actions.ts +197 -0
- package/src/app-runtime/measure-ref.ts +19 -0
- package/src/app-runtime/navigation-actions.ts +213 -0
- package/src/app-runtime/project-actions.ts +188 -0
- package/src/app-runtime/prompt-injection.ts +123 -0
- package/src/app-runtime/selection.ts +29 -0
- package/src/app-runtime/settings-actions.ts +156 -0
- package/src/app-runtime/setup-actions.ts +237 -0
- package/src/app-runtime/side-effect-context.ts +33 -0
- package/src/app-runtime/side-effects.ts +302 -1541
- package/src/app-runtime/snippet-actions.ts +3 -2
- package/src/app-runtime/tab-actions.ts +218 -0
- package/src/app-runtime/tab-runtime-timeouts.ts +1 -1
- package/src/app-runtime/use-auto-commit-driver.ts +14 -13
- package/src/app-runtime/use-backend-runtime.ts +12 -11
- package/src/app-runtime/use-directory-search.ts +5 -4
- package/src/app-runtime/use-mouse-handlers.ts +2 -1
- package/src/app-runtime/{use-workspace-autosave.ts → use-project-autosave.ts} +4 -4
- package/src/app-runtime/use-renderer-bindings.ts +2 -1
- package/src/app-runtime/use-setup-runner.ts +96 -0
- package/src/app-runtime/use-terminal-resize.ts +18 -14
- package/src/app-runtime/workspace-actions.ts +366 -0
- package/src/app-runtime/workspace-activity.ts +138 -0
- package/src/app-runtime/workspace-naming.ts +90 -0
- package/src/app.tsx +93 -48
- package/src/assets/sounds/bell.wav +0 -0
- package/src/assets/sounds/ding.wav +0 -0
- package/src/assets/sounds/plane.wav +0 -0
- package/src/cli/client/daemon-client.ts +2 -2
- package/src/cli/client/project-resolver.ts +112 -0
- package/src/cli/commands/project/close.ts +32 -0
- package/src/cli/commands/project/create.ts +93 -0
- package/src/cli/commands/project/list.ts +25 -0
- package/src/cli/commands/project/show.ts +32 -0
- package/src/cli/commands/{workspace → project}/switch.ts +19 -19
- package/src/cli/commands/tab/await.ts +2 -2
- package/src/cli/commands/tab/close.ts +3 -3
- package/src/cli/commands/tab/create.ts +74 -73
- package/src/cli/commands/tab/focus.ts +3 -3
- package/src/cli/commands/tab/list.ts +6 -6
- package/src/cli/commands/tab/run.ts +2 -2
- package/src/cli/commands/tab/send.ts +2 -2
- package/src/cli/commands/tab/snapshot.ts +2 -2
- package/src/cli/commands/tab/tail.ts +2 -2
- package/src/cli/commands/tab/wait.ts +2 -2
- package/src/cli/commands/worker/await.ts +3 -3
- package/src/cli/commands/worker/doctor.ts +30 -30
- package/src/cli/commands/worker/list.ts +15 -15
- package/src/cli/commands/worker/prompt.ts +3 -3
- package/src/cli/commands/worker/run.ts +23 -23
- package/src/cli/commands/worker/shared.ts +53 -59
- package/src/cli/commands/worker/stop.ts +29 -29
- package/src/cli/commands/worker/submit.ts +3 -3
- package/src/cli/commands/{worktree → workspace}/create-core.ts +26 -26
- package/src/cli/commands/workspace/create.ts +30 -68
- package/src/cli/commands/workspace/list.ts +52 -9
- package/src/cli/commands/workspace/remove.ts +81 -0
- package/src/cli/completion/plan.ts +2 -2
- package/src/cli/completion/sources.ts +18 -18
- package/src/cli/context.ts +13 -13
- package/src/cli/flags.ts +30 -10
- package/src/cli/index.ts +26 -16
- package/src/cli/output.ts +1 -1
- package/src/cli/registry.ts +12 -12
- package/src/config/loader.ts +16 -5
- package/src/config.ts +70 -112
- package/src/daemon/catalog-writer.ts +67 -67
- package/src/daemon/daemon.ts +205 -201
- package/src/daemon/session-manager.ts +39 -39
- package/src/daemon/session-registry.ts +14 -14
- package/src/git/divergence.ts +33 -2
- package/src/git/git-poller.ts +1 -1
- package/src/git/git-status.ts +2 -2
- package/src/git/{move-worktree.ts → move-workspace.ts} +5 -5
- package/src/git/pr-status.ts +1 -1
- package/src/git/repo-discovery.ts +1 -1
- package/src/git/use-repo-discovery.ts +1 -1
- package/src/git/workspace-branch-poller.ts +54 -0
- package/src/git/workspace-divergence-poller.ts +65 -0
- package/src/git/worktree.ts +29 -0
- package/src/index.tsx +4 -4
- package/src/input/keymap/help-entries.ts +7 -5
- package/src/input/modes/bridge.ts +13 -12
- package/src/input/modes/handlers/shared.ts +1 -1
- package/src/input/modes/transitions.ts +34 -21
- package/src/input/modes/types.ts +48 -31
- package/src/ipc/manager-protocol.ts +44 -44
- package/src/ipc/protocol.ts +192 -166
- package/src/platform/play-sound.ts +184 -0
- package/src/platform/project-search.ts +8 -8
- package/src/platform/worktree-paths.ts +8 -6
- package/src/pty/assistant-question-extractor.ts +1 -1
- package/src/pty/assistant-status-detection-loop.ts +79 -55
- package/src/pty/assistant-status-detector.ts +40 -15
- package/src/pty/command-registry.ts +81 -1
- package/src/restart-terminal-manager.ts +1 -1
- package/src/services/ai-usage/provider.ts +9 -2
- package/src/services/ai-usage/spawn.ts +19 -6
- package/src/session-backend/bootstrap.ts +4 -4
- package/src/session-backend/local-session-backend.ts +78 -75
- package/src/session-backend/remote-session-backend.ts +64 -52
- package/src/session-backend/types.ts +43 -32
- package/src/settings/live.ts +90 -0
- package/src/settings/search.ts +43 -0
- package/src/settings/sections/about.ts +49 -0
- package/src/settings/sections/appearance.ts +54 -0
- package/src/settings/sections/automation.ts +105 -0
- package/src/settings/sections/commands.ts +72 -0
- package/src/settings/sections/editor.ts +56 -0
- package/src/settings/sections/experimental.ts +57 -0
- package/src/settings/sections/git.ts +112 -0
- package/src/settings/sections/index.ts +95 -0
- package/src/settings/sections/integrations.ts +23 -0
- package/src/settings/sections/layout.ts +72 -0
- package/src/settings/sections/notifications.ts +99 -0
- package/src/settings/sections/setup.ts +54 -0
- package/src/settings/sections/status-bar.ts +63 -0
- package/src/settings/settings-store.ts +207 -0
- package/src/settings/types.ts +108 -0
- package/src/snippets/run-shell-var.ts +48 -22
- package/src/state/actions.ts +342 -0
- package/src/state/app-store.ts +2 -1
- package/src/state/bars.ts +1 -1
- package/src/state/dispatch-ref.ts +1 -1
- package/src/state/layout-resize.ts +2 -2
- package/src/state/project-catalog.ts +275 -0
- package/src/state/project-data.ts +143 -0
- package/src/state/{session-persistence.ts → project-persistence.ts} +74 -68
- package/src/state/project-save.ts +46 -0
- package/src/state/project-workspaces.ts +392 -0
- package/src/state/reducers/auto-commit-state.ts +11 -10
- package/src/state/reducers/git-commit-modal-state.ts +122 -0
- package/src/state/reducers/git-mode-state.ts +1 -1
- package/src/state/reducers/git-panel-state.ts +10 -6
- package/src/state/reducers/modal-state.ts +290 -681
- package/src/state/reducers/multi-repo-state.ts +3 -6
- package/src/state/reducers/project-state.ts +312 -0
- package/src/state/reducers/settings-state.ts +80 -0
- package/src/state/reducers/tab-state.ts +107 -60
- package/src/state/reducers/ui-state.ts +4 -3
- package/src/state/selectors.ts +49 -37
- package/src/state/store.ts +57 -24
- package/src/state/types.ts +244 -405
- package/src/state/validation.ts +14 -12
- package/src/terminal-manager/manager-client.ts +32 -32
- package/src/terminal-manager/terminal-manager.ts +24 -24
- package/src/ui/components/git/git-panel.tsx +2 -2
- package/src/ui/components/git/git-view.tsx +12 -12
- package/src/ui/components/git/image-diff/image-diff-view.tsx +1 -1
- package/src/ui/components/git/pane/git-pane-widget.tsx +7 -7
- package/src/ui/components/layout/sidebar/project-list.tsx +444 -0
- package/src/ui/components/layout/sidebar/tab-item.tsx +27 -12
- package/src/ui/components/layout/sidebar/use-sidebar-auto-scroll.ts +1 -1
- package/src/ui/components/layout/sidebar/workspace-row.tsx +253 -0
- package/src/ui/components/layout/status-bar.tsx +6 -2
- package/src/ui/components/layout/terminal-pane.tsx +34 -29
- package/src/ui/components/layout/top-tab-bar.tsx +46 -36
- package/src/ui/components/modals/git/git-commit-modal.tsx +8 -8
- package/src/ui/components/modals/{sessions/create-session-modal.tsx → projects/create-project-modal.tsx} +12 -12
- package/src/ui/components/modals/{sessions/session-name-modal.tsx → projects/project-name-modal.tsx} +2 -2
- package/src/ui/components/modals/{sessions/session-picker-modal.tsx → projects/project-picker-modal.tsx} +33 -35
- package/src/ui/components/modals/settings/settings-search-modal.tsx +70 -0
- package/src/ui/components/modals/shared/form.tsx +34 -22
- package/src/ui/components/modals/shared/picker.tsx +10 -10
- package/src/ui/components/modals/shared/{worktree-delete-confirm.tsx → workspace-delete-confirm.tsx} +9 -9
- package/src/ui/components/modals/tabs/new-tab-modal.tsx +30 -324
- package/src/ui/components/modals/workspace/create-workspace-modal.tsx +101 -0
- package/src/ui/components/modals/{worktree/worktree-move-confirm-modal.tsx → workspace/workspace-move-confirm-modal.tsx} +5 -5
- package/src/ui/components/modals/{worktree/worktree-move-modal.tsx → workspace/workspace-move-modal.tsx} +29 -27
- package/src/ui/components/primitives/input-field.tsx +7 -3
- package/src/ui/components/primitives/surface.tsx +3 -0
- package/src/ui/components/settings/row-value.tsx +74 -0
- package/src/ui/components/settings/settings-row.tsx +78 -0
- package/src/ui/components/settings/settings-view.tsx +169 -0
- package/src/ui/components/setup/setup-widget.tsx +152 -0
- package/src/ui/flash/build-labels.ts +27 -27
- package/src/ui/hooks/use-activity-sprite.ts +73 -0
- package/src/ui/hooks/use-scroll-active-into-view.ts +26 -0
- package/src/ui/{session-ordering.ts → project-ordering.ts} +4 -4
- package/src/ui/root.tsx +139 -121
- package/src/ui/status-bar-model.ts +48 -34
- package/src/ui/terminal-graphics/kitty.ts +28 -2
- package/src/ui/terminal-graphics/sprites/done@330/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/done@330/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/idle@1000/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/idle@1000/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/waiting@170/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/waiting@170/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/0.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/1.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/2.png +0 -0
- package/src/ui/terminal-graphics/sprites/working@150/3.png +0 -0
- package/src/ui/terminal-graphics/sprites.ts +246 -0
- package/src/ui/truncate.ts +7 -0
- package/src/ui/widgets/registry.tsx +6 -3
- package/src/ui/widgets/widget-context-menu.ts +26 -10
- package/src/update.ts +2 -2
- package/src/app-runtime/session-actions.ts +0 -187
- package/src/cli/client/workspace-resolver.ts +0 -110
- package/src/cli/commands/workspace/close.ts +0 -32
- package/src/cli/commands/workspace/show.ts +0 -32
- package/src/cli/commands/worktree/create.ts +0 -55
- package/src/cli/commands/worktree/list.ts +0 -68
- package/src/cli/commands/worktree/remove.ts +0 -81
- package/src/git/worktree-branch-poller.ts +0 -54
- package/src/git/worktree-divergence-poller.ts +0 -59
- package/src/state/reducers/session-state.ts +0 -262
- package/src/state/session-catalog.ts +0 -143
- package/src/state/session-worktrees.ts +0 -260
- package/src/state/workspace-save.ts +0 -43
- package/src/ui/components/layout/sidebar/use-top-tab-bar-auto-scroll.ts +0 -30
- package/src/ui/components/layout/sidebar/workspace-list.tsx +0 -418
- package/src/ui/components/layout/sidebar/worktree-row.tsx +0 -149
- /package/src/ui/{components/git/image-diff → terminal-graphics}/dimensions.ts +0 -0
|
@@ -6,18 +6,22 @@ type SupportedModalType = Exclude<ModalType, null>
|
|
|
6
6
|
const DIRECT_FOCUS_MODE_IDS: Partial<Record<FocusMode, ModeId>> = {
|
|
7
7
|
'git': 'git-mode',
|
|
8
8
|
'navigation': 'navigation',
|
|
9
|
+
'settings': 'settings',
|
|
9
10
|
'terminal-input': 'terminal-input',
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const COMMAND_EDIT_MODE_IDS: Partial<Record<SupportedModalType, ModeId>> = {
|
|
13
|
-
'create-
|
|
14
|
+
'create-project': 'modal.create-project',
|
|
15
|
+
'create-workspace': 'modal.create-workspace',
|
|
14
16
|
'git-commit': 'modal.git-commit',
|
|
15
17
|
'help': 'modal.help.filtering',
|
|
16
18
|
'new-tab': 'modal.new-tab.command-edit',
|
|
19
|
+
'project-name': 'modal.project-name',
|
|
20
|
+
'project-picker': 'modal.project-picker.filtering',
|
|
17
21
|
'rename-tab': 'modal.rename-tab',
|
|
18
|
-
'rename-
|
|
19
|
-
'
|
|
20
|
-
'
|
|
22
|
+
'rename-workspace': 'modal.rename-workspace',
|
|
23
|
+
'setting-text': 'modal.setting-text',
|
|
24
|
+
'settings-search': 'modal.settings-search.filtering',
|
|
21
25
|
'snippet-editor': 'modal.snippet-editor',
|
|
22
26
|
'snippet-picker': 'modal.snippet-picker.filtering',
|
|
23
27
|
'split-picker': 'modal.split-picker',
|
|
@@ -27,9 +31,9 @@ const COMMAND_EDIT_MODE_IDS: Partial<Record<SupportedModalType, ModeId>> = {
|
|
|
27
31
|
const MODAL_MODE_IDS: Partial<Record<SupportedModalType, ModeId>> = {
|
|
28
32
|
'ai-usage': 'modal.ai-usage',
|
|
29
33
|
'update-available': 'modal.update-available',
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
34
|
+
'workspace-delete-confirm': 'modal.workspace-delete-confirm',
|
|
35
|
+
'workspace-move': 'modal.workspace-move',
|
|
36
|
+
'workspace-move-confirm': 'modal.workspace-move-confirm',
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export function deriveModeId(state: AppState): ModeId {
|
|
@@ -41,8 +45,8 @@ export function deriveModeId(state: AppState): ModeId {
|
|
|
41
45
|
|
|
42
46
|
// Overlay on top of git mode without flipping focusMode (like help) — route
|
|
43
47
|
// input to the picker while it's open even though focus stays 'git'.
|
|
44
|
-
if (state.modal.type === '
|
|
45
|
-
return 'modal.
|
|
48
|
+
if (state.modal.type === 'workspace-move') {
|
|
49
|
+
return 'modal.workspace-move'
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
// Flash-jump overlay: same pattern — renders on top of navigation, all
|
|
@@ -60,9 +64,6 @@ export function deriveModeId(state: AppState): ModeId {
|
|
|
60
64
|
if (state.modal.type === 'new-tab' && state.modal.editingCommand !== null) {
|
|
61
65
|
return 'modal.new-tab.editing-command'
|
|
62
66
|
}
|
|
63
|
-
if (state.modal.type === 'new-tab' && state.modal.worktreeDeletePrompt !== null) {
|
|
64
|
-
return 'modal.new-tab.worktree-delete-confirm'
|
|
65
|
-
}
|
|
66
67
|
if (state.modal.type === 'git-commit' && state.modal.stage === 'confirm') {
|
|
67
68
|
return 'modal.git-commit.confirm'
|
|
68
69
|
}
|
|
@@ -1,51 +1,64 @@
|
|
|
1
1
|
import type { ModeId } from './types'
|
|
2
2
|
|
|
3
3
|
const TRANSITIONS: Record<ModeId, readonly ModeId[]> = {
|
|
4
|
-
'git-mode': ['navigation', 'modal.git-commit', 'modal.
|
|
4
|
+
'git-mode': ['navigation', 'modal.git-commit', 'modal.workspace-move'],
|
|
5
5
|
'modal.ai-usage': ['navigation', 'terminal-input'],
|
|
6
|
-
'modal.create-
|
|
6
|
+
'modal.create-project': ['navigation', 'modal.project-picker.filtering'],
|
|
7
|
+
'modal.create-workspace': ['navigation', 'terminal-input'],
|
|
7
8
|
'modal.flash-jump': ['navigation'],
|
|
8
9
|
'modal.git-commit': ['git-mode', 'modal.git-commit.confirm', 'modal.git-commit.generating'],
|
|
9
10
|
'modal.git-commit.confirm': ['modal.git-commit', 'git-mode'],
|
|
10
11
|
'modal.git-commit.generating': ['modal.git-commit', 'modal.git-commit.confirm', 'git-mode'],
|
|
11
12
|
'modal.help.filtering': ['navigation'],
|
|
12
|
-
'modal.new-tab.command-edit': [
|
|
13
|
-
'navigation',
|
|
14
|
-
'modal.new-tab.editing-command',
|
|
15
|
-
'modal.new-tab.worktree-delete-confirm',
|
|
16
|
-
],
|
|
13
|
+
'modal.new-tab.command-edit': ['navigation', 'modal.new-tab.editing-command'],
|
|
17
14
|
'modal.new-tab.editing-command': ['navigation', 'modal.new-tab.command-edit'],
|
|
18
|
-
'modal.
|
|
15
|
+
'modal.project-name': ['modal.project-picker.filtering', 'navigation'],
|
|
16
|
+
'modal.project-picker.filtering': ['navigation', 'modal.project-name', 'modal.create-project'],
|
|
19
17
|
'modal.rename-tab': ['navigation'],
|
|
20
|
-
'modal.rename-
|
|
21
|
-
'modal.
|
|
22
|
-
'modal.
|
|
18
|
+
'modal.rename-workspace': ['navigation'],
|
|
19
|
+
'modal.setting-text': ['settings'],
|
|
20
|
+
'modal.settings-search.filtering': ['settings'],
|
|
23
21
|
'modal.snippet-editor': ['navigation', 'modal.snippet-picker.filtering'],
|
|
24
|
-
|
|
22
|
+
// Both pickers are reachable from the settings screen as well as from the
|
|
23
|
+
// panes, and `returnTo` sends each one back where it came from.
|
|
24
|
+
'modal.snippet-picker.filtering': ['navigation', 'settings', 'modal.snippet-editor'],
|
|
25
25
|
'modal.split-picker': ['navigation', 'terminal-input'],
|
|
26
|
-
'modal.theme-picker.filtering': ['navigation'],
|
|
26
|
+
'modal.theme-picker.filtering': ['navigation', 'settings'],
|
|
27
27
|
'modal.update-available': ['navigation'],
|
|
28
|
-
'modal.
|
|
29
|
-
'modal.
|
|
30
|
-
'modal.
|
|
28
|
+
'modal.workspace-delete-confirm': ['navigation'],
|
|
29
|
+
'modal.workspace-move': ['git-mode', 'navigation'],
|
|
30
|
+
'modal.workspace-move-confirm': ['navigation'],
|
|
31
31
|
'navigation': [
|
|
32
32
|
'terminal-input',
|
|
33
|
+
'modal.create-workspace',
|
|
33
34
|
'modal.new-tab.command-edit',
|
|
34
35
|
'modal.new-tab.editing-command',
|
|
35
|
-
'modal.
|
|
36
|
+
'modal.project-picker.filtering',
|
|
36
37
|
'modal.help.filtering',
|
|
37
38
|
'modal.snippet-picker.filtering',
|
|
38
39
|
'modal.theme-picker.filtering',
|
|
39
40
|
'modal.rename-tab',
|
|
40
|
-
'modal.rename-
|
|
41
|
+
'modal.rename-workspace',
|
|
41
42
|
'modal.update-available',
|
|
42
43
|
'modal.ai-usage',
|
|
43
|
-
'modal.
|
|
44
|
-
'modal.
|
|
44
|
+
'modal.workspace-delete-confirm',
|
|
45
|
+
'modal.workspace-move-confirm',
|
|
45
46
|
'modal.flash-jump',
|
|
46
47
|
'git-mode',
|
|
48
|
+
'settings',
|
|
49
|
+
],
|
|
50
|
+
// The help overlay opens over settings without a transition (it leaves
|
|
51
|
+
// focusMode alone). The two pickers an action row hands over to are dispatched
|
|
52
|
+
// directly rather than through a KeyResult, but they are listed because that is
|
|
53
|
+
// what this table is for: saying where a mode can go.
|
|
54
|
+
'settings': [
|
|
55
|
+
'navigation',
|
|
56
|
+
'modal.setting-text',
|
|
57
|
+
'modal.settings-search.filtering',
|
|
58
|
+
'modal.theme-picker.filtering',
|
|
59
|
+
'modal.snippet-picker.filtering',
|
|
47
60
|
],
|
|
48
|
-
'terminal-input': ['navigation', 'modal.split-picker', 'modal.ai-usage'],
|
|
61
|
+
'terminal-input': ['navigation', 'modal.split-picker', 'modal.ai-usage', 'settings'],
|
|
49
62
|
}
|
|
50
63
|
|
|
51
64
|
export function isValidTransition(from: ModeId, to: ModeId): boolean {
|
package/src/input/modes/types.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { KeyEvent } from '@opentui/core'
|
|
2
2
|
|
|
3
|
+
import type { AppAction } from '../../state/actions'
|
|
3
4
|
import type { SplitDirection } from '../../state/layout-tree'
|
|
4
|
-
import type {
|
|
5
|
+
import type { AppState, GitFileListMode, TabSession } from '../../state/types'
|
|
5
6
|
|
|
6
7
|
export type ModeId =
|
|
7
8
|
| 'navigation'
|
|
@@ -9,13 +10,15 @@ export type ModeId =
|
|
|
9
10
|
| 'git-mode'
|
|
10
11
|
| 'modal.new-tab.command-edit'
|
|
11
12
|
| 'modal.new-tab.editing-command'
|
|
12
|
-
| 'modal.
|
|
13
|
-
| 'modal.
|
|
14
|
-
| 'modal.
|
|
15
|
-
| 'modal.
|
|
16
|
-
| 'modal.create-
|
|
13
|
+
| 'modal.workspace-delete-confirm'
|
|
14
|
+
| 'modal.project-picker.filtering'
|
|
15
|
+
| 'modal.project-name'
|
|
16
|
+
| 'modal.create-project'
|
|
17
|
+
| 'modal.create-workspace'
|
|
17
18
|
| 'modal.rename-tab'
|
|
18
|
-
| 'modal.rename-
|
|
19
|
+
| 'modal.rename-workspace'
|
|
20
|
+
| 'modal.setting-text'
|
|
21
|
+
| 'modal.settings-search.filtering'
|
|
19
22
|
| 'modal.snippet-picker.filtering'
|
|
20
23
|
| 'modal.snippet-editor'
|
|
21
24
|
| 'modal.theme-picker.filtering'
|
|
@@ -25,20 +28,23 @@ export type ModeId =
|
|
|
25
28
|
| 'modal.git-commit.confirm'
|
|
26
29
|
| 'modal.git-commit.generating'
|
|
27
30
|
| 'modal.update-available'
|
|
28
|
-
| 'modal.
|
|
29
|
-
| 'modal.
|
|
31
|
+
| 'modal.workspace-move'
|
|
32
|
+
| 'modal.workspace-move-confirm'
|
|
30
33
|
| 'modal.ai-usage'
|
|
31
34
|
| 'modal.flash-jump'
|
|
35
|
+
| 'settings'
|
|
32
36
|
|
|
33
37
|
export type SideEffect =
|
|
34
38
|
| { type: 'quit'; state: AppState }
|
|
39
|
+
| { type: 'open-new-tab' }
|
|
35
40
|
| { type: 'launch-selected-assistant' }
|
|
36
|
-
| { type: 'load-new-tab-base-branches' }
|
|
37
41
|
| { type: 'edit-selected-assistant' }
|
|
38
|
-
| { type: 'confirm-selected-
|
|
39
|
-
| { type: 'delete-selected-
|
|
40
|
-
| { type: 'open-rename-selected-
|
|
41
|
-
| { type: 'create-
|
|
42
|
+
| { type: 'confirm-selected-project' }
|
|
43
|
+
| { type: 'delete-selected-project' }
|
|
44
|
+
| { type: 'open-rename-selected-project' }
|
|
45
|
+
| { type: 'create-project'; name: string; projectPath?: string }
|
|
46
|
+
| { type: 'create-workspace' }
|
|
47
|
+
| { type: 'load-create-workspace-base-branches' }
|
|
42
48
|
| { type: 'close-tab'; tabId: string }
|
|
43
49
|
| { type: 'restart-tab'; tab: TabSession }
|
|
44
50
|
| { type: 'paste-selected-snippet' }
|
|
@@ -51,7 +57,7 @@ export type SideEffect =
|
|
|
51
57
|
| { type: 'apply-theme'; action: 'restore' }
|
|
52
58
|
| { type: 'apply-theme'; action: 'confirm' }
|
|
53
59
|
| { type: 'apply-theme'; action: 'preview'; delta: 1 | -1 }
|
|
54
|
-
| { type: 'rename-
|
|
60
|
+
| { type: 'rename-project'; projectId: string; name: string }
|
|
55
61
|
| { type: 'rename-tab'; tabId: string; title: string }
|
|
56
62
|
| {
|
|
57
63
|
type: 'split-pane'
|
|
@@ -71,40 +77,51 @@ export type SideEffect =
|
|
|
71
77
|
| { type: 'git-rm'; path: string }
|
|
72
78
|
| { type: 'git-commit'; title: string; body: string }
|
|
73
79
|
| { type: 'git-commit-auto'; title: string; body: string }
|
|
74
|
-
| { type: 'generate-auto-commit-now';
|
|
80
|
+
| { type: 'generate-auto-commit-now'; projectId: string }
|
|
75
81
|
| { type: 'git-push' }
|
|
76
82
|
| { type: 'confirm-update-selection' }
|
|
77
|
-
| { type: 'switch-
|
|
83
|
+
| { type: 'switch-project-by-index'; index: number; workspaceId?: string }
|
|
78
84
|
| { type: 'cycle-sidebar-item'; direction: 1 | -1 }
|
|
79
85
|
| { type: 'switch-tab-by-index'; index: number }
|
|
80
|
-
| { type: 'delete-
|
|
86
|
+
| { type: 'delete-project'; projectId: string }
|
|
81
87
|
| {
|
|
82
|
-
type: 'delete-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
type: 'delete-workspace'
|
|
89
|
+
projectId: string
|
|
90
|
+
workspaceId: string
|
|
85
91
|
// Force the git worktree removal (discards uncommitted changes in the
|
|
86
|
-
//
|
|
92
|
+
// workspace). Also implies closing the workspace's tabs.
|
|
87
93
|
force?: boolean
|
|
88
|
-
// Close the
|
|
89
|
-
// sidebar "Remove
|
|
90
|
-
// refusing to discard uncommitted work in a temp
|
|
94
|
+
// Close the workspace's tabs without forcing the git removal. Lets the
|
|
95
|
+
// sidebar "Remove workspace" clean up tabs (avoiding orphans) while still
|
|
96
|
+
// refusing to discard uncommitted work in a temp workspace.
|
|
91
97
|
closeTabs?: boolean
|
|
92
98
|
}
|
|
93
99
|
| {
|
|
94
|
-
type: 'move-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
type: 'move-workspace'
|
|
101
|
+
projectId: string
|
|
102
|
+
sourceWorkspaceId: string
|
|
103
|
+
targetWorkspaceId: string
|
|
98
104
|
deleteSource?: boolean
|
|
99
|
-
// Retry flags set by the
|
|
105
|
+
// Retry flags set by the workspace-move-confirm dialog.
|
|
100
106
|
stashTarget?: boolean
|
|
101
107
|
keepConflicts?: boolean
|
|
102
108
|
}
|
|
103
|
-
| { type: 'load-
|
|
109
|
+
| { type: 'load-workspace-move-stats' }
|
|
104
110
|
| { type: 'toggle-transparent' }
|
|
105
111
|
| { type: 'toggle-mode' }
|
|
106
112
|
| { type: 'open-file-in-editor'; path: string }
|
|
107
113
|
| { type: 'open-selected-snippet-source-in-editor' }
|
|
114
|
+
| { type: 'run-setup' }
|
|
115
|
+
| { type: 'stop-setup' }
|
|
116
|
+
| { type: 'configure-setup-script'; projectId?: string }
|
|
117
|
+
| { type: 'ask-agent-for-setup-script' }
|
|
118
|
+
| { type: 'promote-setup-tab' }
|
|
119
|
+
/** Toggle a checkbox, cycle an enum, run a row's action — whatever the row is. */
|
|
120
|
+
| { type: 'activate-settings-row' }
|
|
121
|
+
| { type: 'adjust-settings-row'; delta: 1 | -1 }
|
|
122
|
+
| { type: 'reset-settings-row' }
|
|
123
|
+
| { type: 'confirm-settings-search' }
|
|
124
|
+
| { type: 'commit-setting-text'; settingId: string; value: string }
|
|
108
125
|
|
|
109
126
|
export interface KeyResult {
|
|
110
127
|
actions: AppAction[]
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
ProjectSnapshotV1,
|
|
2
3
|
TabSession,
|
|
3
4
|
TerminalModeState,
|
|
4
5
|
TerminalSnapshot,
|
|
5
|
-
WorkspaceSnapshotV1,
|
|
6
6
|
} from '../state/types'
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { isProjectSnapshotV1 } from '../state/validation'
|
|
9
9
|
import {
|
|
10
10
|
getProcessVersion,
|
|
11
11
|
IpcProtocolError,
|
|
@@ -36,13 +36,13 @@ import {
|
|
|
36
36
|
// v9: additive — `tabMetadata` updates titles and auto-rename state without
|
|
37
37
|
// restarting PTYs. Capability-gated; MIN remains at 8.
|
|
38
38
|
//
|
|
39
|
-
// v10: additive — `workerName` persists a
|
|
39
|
+
// v10: additive — `workerName` persists a project-scoped orchestration
|
|
40
40
|
// handle on tabs created through the headless worker facade.
|
|
41
41
|
//
|
|
42
42
|
// v11: breaking release boundary — force a fresh terminal-manager so named
|
|
43
43
|
// worker metadata is guaranteed to survive daemon reattach and process swaps.
|
|
44
|
-
export const MANAGER_PROTOCOL_MIN_VERSION =
|
|
45
|
-
export const MANAGER_PROTOCOL_VERSION =
|
|
44
|
+
export const MANAGER_PROTOCOL_MIN_VERSION = 12
|
|
45
|
+
export const MANAGER_PROTOCOL_VERSION = 12
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Capability strings advertised by *this* process in its `helloResult`. New
|
|
@@ -52,7 +52,7 @@ export const MANAGER_PROTOCOL_VERSION = 11
|
|
|
52
52
|
*/
|
|
53
53
|
export const MANAGER_PROTOCOL_CAPABILITIES: readonly string[] = [
|
|
54
54
|
'setBroadcastEnabled',
|
|
55
|
-
'
|
|
55
|
+
'createTabWorkspaceId',
|
|
56
56
|
'tabMetadata',
|
|
57
57
|
'workerMetadata',
|
|
58
58
|
]
|
|
@@ -96,10 +96,10 @@ export interface ManagerHelloResult {
|
|
|
96
96
|
|
|
97
97
|
export interface ManagerAttachRequest {
|
|
98
98
|
protocolVersion: number
|
|
99
|
-
|
|
99
|
+
projectId: string
|
|
100
100
|
cols: number
|
|
101
101
|
rows: number
|
|
102
|
-
|
|
102
|
+
projectSnapshot?: ProjectSnapshotV1
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export interface ManagerAttachResult {
|
|
@@ -115,7 +115,7 @@ export type ManagerRequest =
|
|
|
115
115
|
id: string
|
|
116
116
|
type: 'createTab'
|
|
117
117
|
payload: {
|
|
118
|
-
|
|
118
|
+
projectId: string
|
|
119
119
|
tabId: string
|
|
120
120
|
assistant: TabSession['assistant']
|
|
121
121
|
title: string
|
|
@@ -127,22 +127,22 @@ export type ManagerRequest =
|
|
|
127
127
|
/** Extra env vars merged into the spawned PTY's environment. */
|
|
128
128
|
env?: Record<string, string>
|
|
129
129
|
/**
|
|
130
|
-
*
|
|
131
|
-
* `
|
|
130
|
+
* Workspace this tab belongs to (UI grouping). Capability-gated on
|
|
131
|
+
* `createTabWorkspaceId`. Pre-cap TMs silently drop the field, which
|
|
132
132
|
* matches the previous behaviour where every new tab had
|
|
133
|
-
* `
|
|
133
|
+
* `workspaceId = undefined`.
|
|
134
134
|
*/
|
|
135
|
-
|
|
135
|
+
workspaceId?: string
|
|
136
136
|
workerName?: string
|
|
137
137
|
autoRenameStatus?: 'eligible' | 'attempted'
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
| { id: string; type: 'write'; payload: {
|
|
140
|
+
| { id: string; type: 'write'; payload: { projectId: string; tabId: string; data: string } }
|
|
141
141
|
| {
|
|
142
142
|
id: string
|
|
143
143
|
type: 'updateTabMetadata'
|
|
144
144
|
payload: {
|
|
145
|
-
|
|
145
|
+
projectId: string
|
|
146
146
|
tabId: string
|
|
147
147
|
title?: string
|
|
148
148
|
autoRenameStatus?: 'eligible' | 'attempted'
|
|
@@ -152,7 +152,7 @@ export type ManagerRequest =
|
|
|
152
152
|
id: string
|
|
153
153
|
type: 'resizeClient'
|
|
154
154
|
payload: {
|
|
155
|
-
|
|
155
|
+
projectId: string
|
|
156
156
|
cols: number
|
|
157
157
|
rows: number
|
|
158
158
|
}
|
|
@@ -161,7 +161,7 @@ export type ManagerRequest =
|
|
|
161
161
|
id: string
|
|
162
162
|
type: 'resizeTab'
|
|
163
163
|
payload: {
|
|
164
|
-
|
|
164
|
+
projectId: string
|
|
165
165
|
tabId: string
|
|
166
166
|
cols: number
|
|
167
167
|
rows: number
|
|
@@ -170,16 +170,16 @@ export type ManagerRequest =
|
|
|
170
170
|
| {
|
|
171
171
|
id: string
|
|
172
172
|
type: 'scrollToBottom'
|
|
173
|
-
payload: {
|
|
173
|
+
payload: { projectId: string; tabId: string }
|
|
174
174
|
}
|
|
175
175
|
| {
|
|
176
176
|
id: string
|
|
177
177
|
type: 'scroll'
|
|
178
|
-
payload: {
|
|
178
|
+
payload: { projectId: string; tabId: string; deltaLines: number }
|
|
179
179
|
}
|
|
180
|
-
| { id: string; type: 'setActiveTab'; payload: {
|
|
181
|
-
| { id: string; type: 'closeTab'; payload: {
|
|
182
|
-
| { id: string; type: 'disposeSession'; payload: {
|
|
180
|
+
| { id: string; type: 'setActiveTab'; payload: { projectId: string; tabId: string | null } }
|
|
181
|
+
| { id: string; type: 'closeTab'; payload: { projectId: string; tabId: string } }
|
|
182
|
+
| { id: string; type: 'disposeSession'; payload: { projectId: string } }
|
|
183
183
|
| { id: string; type: 'ping'; payload: Record<string, never> }
|
|
184
184
|
| { id: string; type: 'setBroadcastEnabled'; payload: { enabled: boolean } }
|
|
185
185
|
|
|
@@ -193,14 +193,14 @@ export type ManagerEvent =
|
|
|
193
193
|
| {
|
|
194
194
|
type: 'tabRender'
|
|
195
195
|
payload: {
|
|
196
|
-
|
|
196
|
+
projectId: string
|
|
197
197
|
tabId: string
|
|
198
198
|
viewport: TerminalSnapshot
|
|
199
199
|
terminalModes: TerminalModeState
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
-
| { type: 'tabExit'; payload: {
|
|
203
|
-
| { type: 'tabError'; payload: {
|
|
202
|
+
| { type: 'tabExit'; payload: { projectId: string; tabId: string; exitCode: number } }
|
|
203
|
+
| { type: 'tabError'; payload: { projectId: string; tabId: string; message: string } }
|
|
204
204
|
|
|
205
205
|
export type ManagerMessage = ManagerRequest | ManagerResponse | ManagerEvent
|
|
206
206
|
|
|
@@ -354,17 +354,17 @@ export function parseManagerRequest(value: unknown): ManagerRequest {
|
|
|
354
354
|
isFiniteNumber(value.payload.protocolVersion),
|
|
355
355
|
'attachSession.protocolVersion must be a number'
|
|
356
356
|
)
|
|
357
|
-
assert(isString(value.payload.
|
|
357
|
+
assert(isString(value.payload.projectId), 'attachSession.projectId must be a string')
|
|
358
358
|
assert(isFiniteNumber(value.payload.cols), 'attachSession.cols must be a number')
|
|
359
359
|
assert(isFiniteNumber(value.payload.rows), 'attachSession.rows must be a number')
|
|
360
360
|
assert(
|
|
361
|
-
value.payload.
|
|
362
|
-
|
|
363
|
-
'attachSession.
|
|
361
|
+
value.payload.projectSnapshot === undefined ||
|
|
362
|
+
isProjectSnapshotV1(value.payload.projectSnapshot),
|
|
363
|
+
'attachSession.projectSnapshot must be a valid project snapshot'
|
|
364
364
|
)
|
|
365
365
|
return value as ManagerRequest
|
|
366
366
|
case 'createTab':
|
|
367
|
-
assert(isString(value.payload.
|
|
367
|
+
assert(isString(value.payload.projectId), 'createTab.projectId must be a string')
|
|
368
368
|
assert(isString(value.payload.tabId), 'createTab.tabId must be a string')
|
|
369
369
|
assert(
|
|
370
370
|
isString(value.payload.assistant) && value.payload.assistant.length > 0,
|
|
@@ -387,8 +387,8 @@ export function parseManagerRequest(value: unknown): ManagerRequest {
|
|
|
387
387
|
'createTab.env must be a string-keyed string record'
|
|
388
388
|
)
|
|
389
389
|
assert(
|
|
390
|
-
value.payload.
|
|
391
|
-
'createTab.
|
|
390
|
+
value.payload.workspaceId === undefined || isString(value.payload.workspaceId),
|
|
391
|
+
'createTab.workspaceId must be a string when present'
|
|
392
392
|
)
|
|
393
393
|
assert(
|
|
394
394
|
value.payload.workerName === undefined || isString(value.payload.workerName),
|
|
@@ -402,12 +402,12 @@ export function parseManagerRequest(value: unknown): ManagerRequest {
|
|
|
402
402
|
)
|
|
403
403
|
return value as ManagerRequest
|
|
404
404
|
case 'write':
|
|
405
|
-
assert(isString(value.payload.
|
|
405
|
+
assert(isString(value.payload.projectId), 'write.projectId must be a string')
|
|
406
406
|
assert(isString(value.payload.tabId), 'write.tabId must be a string')
|
|
407
407
|
assert(isString(value.payload.data), 'write.data must be a string')
|
|
408
408
|
return value as ManagerRequest
|
|
409
409
|
case 'updateTabMetadata':
|
|
410
|
-
assert(isString(value.payload.
|
|
410
|
+
assert(isString(value.payload.projectId), 'updateTabMetadata.projectId must be a string')
|
|
411
411
|
assert(isString(value.payload.tabId), 'updateTabMetadata.tabId must be a string')
|
|
412
412
|
assert(
|
|
413
413
|
value.payload.title === undefined || isString(value.payload.title),
|
|
@@ -421,35 +421,35 @@ export function parseManagerRequest(value: unknown): ManagerRequest {
|
|
|
421
421
|
)
|
|
422
422
|
return value as ManagerRequest
|
|
423
423
|
case 'resizeClient':
|
|
424
|
-
assert(isString(value.payload.
|
|
424
|
+
assert(isString(value.payload.projectId), 'resizeClient.projectId must be a string')
|
|
425
425
|
assert(isFiniteNumber(value.payload.cols), 'resizeClient.cols must be a number')
|
|
426
426
|
assert(isFiniteNumber(value.payload.rows), 'resizeClient.rows must be a number')
|
|
427
427
|
return value as ManagerRequest
|
|
428
428
|
case 'resizeTab':
|
|
429
|
-
assert(isString(value.payload.
|
|
429
|
+
assert(isString(value.payload.projectId), 'resizeTab.projectId must be a string')
|
|
430
430
|
assert(isString(value.payload.tabId), 'resizeTab.tabId must be a string')
|
|
431
431
|
assert(isFiniteNumber(value.payload.cols), 'resizeTab.cols must be a number')
|
|
432
432
|
assert(isFiniteNumber(value.payload.rows), 'resizeTab.rows must be a number')
|
|
433
433
|
return value as ManagerRequest
|
|
434
434
|
case 'scroll':
|
|
435
|
-
assert(isString(value.payload.
|
|
435
|
+
assert(isString(value.payload.projectId), 'scroll.projectId must be a string')
|
|
436
436
|
assert(isString(value.payload.tabId), 'scroll.tabId must be a string')
|
|
437
437
|
assert(isFiniteNumber(value.payload.deltaLines), 'scroll.deltaLines must be a number')
|
|
438
438
|
return value as ManagerRequest
|
|
439
439
|
case 'scrollToBottom':
|
|
440
|
-
assert(isString(value.payload.
|
|
440
|
+
assert(isString(value.payload.projectId), 'scrollToBottom.projectId must be a string')
|
|
441
441
|
assert(isString(value.payload.tabId), 'scrollToBottom.tabId must be a string')
|
|
442
442
|
return value as ManagerRequest
|
|
443
443
|
case 'setActiveTab':
|
|
444
|
-
assert(isString(value.payload.
|
|
444
|
+
assert(isString(value.payload.projectId), 'setActiveTab.projectId must be a string')
|
|
445
445
|
assert(isNullableString(value.payload.tabId), 'setActiveTab.tabId must be a string or null')
|
|
446
446
|
return value as ManagerRequest
|
|
447
447
|
case 'closeTab':
|
|
448
|
-
assert(isString(value.payload.
|
|
448
|
+
assert(isString(value.payload.projectId), 'closeTab.projectId must be a string')
|
|
449
449
|
assert(isString(value.payload.tabId), 'closeTab.tabId must be a string')
|
|
450
450
|
return value as ManagerRequest
|
|
451
451
|
case 'disposeSession':
|
|
452
|
-
assert(isString(value.payload.
|
|
452
|
+
assert(isString(value.payload.projectId), 'disposeSession.projectId must be a string')
|
|
453
453
|
return value as ManagerRequest
|
|
454
454
|
case 'ping':
|
|
455
455
|
return value as ManagerRequest
|
|
@@ -488,18 +488,18 @@ export function parseManagerMessage(value: unknown): ManagerResponse | ManagerEv
|
|
|
488
488
|
assert(isString(value.payload.message), 'error.message must be a string')
|
|
489
489
|
return value as ManagerResponse
|
|
490
490
|
case 'tabRender':
|
|
491
|
-
assert(isString(value.payload.
|
|
491
|
+
assert(isString(value.payload.projectId), 'tabRender.projectId must be a string')
|
|
492
492
|
assert(isString(value.payload.tabId), 'tabRender.tabId must be a string')
|
|
493
493
|
assert(isTerminalSnapshot(value.payload.viewport), 'tabRender.viewport is invalid')
|
|
494
494
|
assert(isTerminalModeState(value.payload.terminalModes), 'tabRender.terminalModes is invalid')
|
|
495
495
|
return value as ManagerEvent
|
|
496
496
|
case 'tabExit':
|
|
497
|
-
assert(isString(value.payload.
|
|
497
|
+
assert(isString(value.payload.projectId), 'tabExit.projectId must be a string')
|
|
498
498
|
assert(isString(value.payload.tabId), 'tabExit.tabId must be a string')
|
|
499
499
|
assert(isFiniteNumber(value.payload.exitCode), 'tabExit.exitCode must be a number')
|
|
500
500
|
return value as ManagerEvent
|
|
501
501
|
case 'tabError':
|
|
502
|
-
assert(isString(value.payload.
|
|
502
|
+
assert(isString(value.payload.projectId), 'tabError.projectId must be a string')
|
|
503
503
|
assert(isString(value.payload.tabId), 'tabError.tabId must be a string')
|
|
504
504
|
assert(isString(value.payload.message), 'tabError.message must be a string')
|
|
505
505
|
return value as ManagerEvent
|