@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
package/src/ipc/protocol.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AssistantId,
|
|
3
|
+
ProjectSnapshotV1,
|
|
4
|
+
ProjectStatus,
|
|
3
5
|
QuestionKind,
|
|
4
|
-
SessionStatus,
|
|
5
6
|
TabActivity,
|
|
6
7
|
TabSession,
|
|
7
8
|
TabStatus,
|
|
8
9
|
TerminalModeState,
|
|
9
10
|
TerminalSnapshot,
|
|
10
|
-
|
|
11
|
-
WorktreeRecord,
|
|
11
|
+
WorkspaceRecord,
|
|
12
12
|
} from '../state/types'
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { isProjectSnapshotV1, isWorkspaceRecord } from '../state/validation'
|
|
15
15
|
|
|
16
16
|
// v9: scroll position is owned entirely by the backend emulator. Dropped the
|
|
17
17
|
// per-tab scroll `intent`/`intents` from resize messages and removed the
|
|
@@ -22,13 +22,13 @@ import { isWorkspaceSnapshotV1, isWorktreeRecord } from '../state/validation'
|
|
|
22
22
|
// v11: additive — exposes `listTabs` (read-only enumeration without `attach`),
|
|
23
23
|
// `attach.thin` (skip server-side resize so a headless CLI can attach
|
|
24
24
|
// alongside a UI without resizing PTYs), and `createTab` cols/rows=0 fallback
|
|
25
|
-
// to the
|
|
25
|
+
// to the project's last attached size. All three are gated behind
|
|
26
26
|
// capabilities; MIN stays at 10 so a v10 UI keeps talking to a v11 daemon
|
|
27
27
|
// (and vice-versa).
|
|
28
28
|
//
|
|
29
|
-
// v12: additive —
|
|
30
|
-
// `
|
|
31
|
-
//
|
|
29
|
+
// v12: additive — project lifecycle requests (`createProject`,
|
|
30
|
+
// `switchProject`, `closeProject`, `announceProjectSwitched`) and
|
|
31
|
+
// workspace record requests (`addWorkspaceRecord`, `removeWorkspaceRecord`),
|
|
32
32
|
// plus matching broadcast events. All capability-gated; MIN stays at 10.
|
|
33
33
|
//
|
|
34
34
|
// v13: additive — agent-orchestration signals. Two new broadcast events,
|
|
@@ -41,13 +41,19 @@ import { isWorkspaceSnapshotV1, isWorktreeRecord } from '../state/validation'
|
|
|
41
41
|
// v14: additive — tab metadata synchronization for manual and automatic
|
|
42
42
|
// renames. The new request/event are capability-gated; MIN stays at 10.
|
|
43
43
|
//
|
|
44
|
-
// v15: additive —
|
|
44
|
+
// v15: additive — project-scoped `workerName` metadata on create, attach,
|
|
45
45
|
// and list results. This powers stable name-or-id orchestration selectors.
|
|
46
46
|
//
|
|
47
47
|
// v16: breaking release boundary — the agent-first worker control plane and
|
|
48
48
|
// its metadata guarantees are now required. Old app/daemon pairs must not mix.
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
//
|
|
50
|
+
// v18: additive — an optional `workspaceId` on the `tabStatus` and
|
|
51
|
+
// `tabTurnComplete` broadcasts. It needs no capability: a client that receives
|
|
52
|
+
// it attributes the tab to a workspace row, and one that doesn't (or a v17
|
|
53
|
+
// daemon that never sends it) simply has no workspace-level indicator. MIN
|
|
54
|
+
// stays at 17 so a running v17 daemon keeps serving until it is restarted.
|
|
55
|
+
export const IPC_PROTOCOL_MIN_VERSION = 17
|
|
56
|
+
export const IPC_PROTOCOL_VERSION = 18
|
|
51
57
|
|
|
52
58
|
/**
|
|
53
59
|
* Capability advertised by a daemon that knows how to drain + handoff its
|
|
@@ -72,7 +78,7 @@ export const IPC_CAPABILITY_THIN_ATTACH = 'thinAttach'
|
|
|
72
78
|
|
|
73
79
|
/**
|
|
74
80
|
* Capability gating `createTab` with `cols: 0` or `rows: 0` meaning "use the
|
|
75
|
-
*
|
|
81
|
+
* project's last attached size". Older daemons would propagate 0 straight to
|
|
76
82
|
* the TM and spawn a zero-sized PTY, so the client only sends zeroes when
|
|
77
83
|
* this capability is advertised.
|
|
78
84
|
*/
|
|
@@ -80,7 +86,7 @@ export const IPC_CAPABILITY_CREATE_TAB_SIZE_FALLBACK = 'createTabSizeFallback'
|
|
|
80
86
|
|
|
81
87
|
/**
|
|
82
88
|
* Capability gating the `tabAdded` server event. When advertised, the daemon
|
|
83
|
-
* fans a `tabAdded` event out to every socket attached to the
|
|
89
|
+
* fans a `tabAdded` event out to every socket attached to the project after
|
|
84
90
|
* a successful `createTab` — that's how a UI process learns about tabs
|
|
85
91
|
* created by a sibling CLI invocation. Pre-cap UIs simply never see the
|
|
86
92
|
* event and continue to discover tabs only via the next `attachResult`.
|
|
@@ -88,30 +94,30 @@ export const IPC_CAPABILITY_CREATE_TAB_SIZE_FALLBACK = 'createTabSizeFallback'
|
|
|
88
94
|
export const IPC_CAPABILITY_TAB_LIFECYCLE_EVENTS = 'tabLifecycleEvents'
|
|
89
95
|
|
|
90
96
|
/**
|
|
91
|
-
* Capability gating the optional `
|
|
92
|
-
* it, the CLI can spawn a tab inside a specific
|
|
93
|
-
*
|
|
97
|
+
* Capability gating the optional `workspaceId` on `createTab` payloads. With
|
|
98
|
+
* it, the CLI can spawn a tab inside a specific workspace of the active
|
|
99
|
+
* project so the UI groups it correctly. Older daemons ignore the field
|
|
94
100
|
* (the parser accepts it but the TM has no knob for it pre-bump).
|
|
95
101
|
*/
|
|
96
|
-
export const
|
|
102
|
+
export const IPC_CAPABILITY_CREATE_TAB_WORKSPACE_ID = 'createTabWorkspaceId'
|
|
97
103
|
|
|
98
104
|
/**
|
|
99
|
-
* v12 — capability gating headless
|
|
100
|
-
* (`
|
|
101
|
-
* `
|
|
102
|
-
* `
|
|
105
|
+
* v12 — capability gating headless project lifecycle requests
|
|
106
|
+
* (`createProject`, `switchProject`, `closeProject`,
|
|
107
|
+
* `announceProjectSwitched`) and their `project*Requested` /
|
|
108
|
+
* `projectSwitched` broadcasts. When a UI is attached the daemon relays
|
|
103
109
|
* the request as an event so the UI's reducer stays authoritative for the
|
|
104
|
-
* live
|
|
110
|
+
* live project snapshot; when no UI is attached the daemon mutates the
|
|
105
111
|
* catalog directly.
|
|
106
112
|
*/
|
|
107
|
-
export const
|
|
113
|
+
export const IPC_CAPABILITY_PROJECT_LIFECYCLE = 'projectLifecycle'
|
|
108
114
|
|
|
109
115
|
/**
|
|
110
|
-
* v12 — capability gating `
|
|
111
|
-
* their `
|
|
112
|
-
* fanout as
|
|
116
|
+
* v12 — capability gating `addWorkspaceRecord` / `removeWorkspaceRecord` and
|
|
117
|
+
* their `workspaceAdded` / `workspaceRemoved` broadcasts. Same UI-vs-headless
|
|
118
|
+
* fanout as projectLifecycle.
|
|
113
119
|
*/
|
|
114
|
-
export const
|
|
120
|
+
export const IPC_CAPABILITY_WORKSPACE_LIFECYCLE_EVENTS = 'workspaceLifecycleEvents'
|
|
115
121
|
export const IPC_CAPABILITY_WORKER_METADATA = 'workerMetadata'
|
|
116
122
|
|
|
117
123
|
/**
|
|
@@ -166,9 +172,9 @@ export const IPC_PROTOCOL_CAPABILITIES: readonly string[] = [
|
|
|
166
172
|
IPC_CAPABILITY_THIN_ATTACH,
|
|
167
173
|
IPC_CAPABILITY_CREATE_TAB_SIZE_FALLBACK,
|
|
168
174
|
IPC_CAPABILITY_TAB_LIFECYCLE_EVENTS,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
IPC_CAPABILITY_CREATE_TAB_WORKSPACE_ID,
|
|
176
|
+
IPC_CAPABILITY_PROJECT_LIFECYCLE,
|
|
177
|
+
IPC_CAPABILITY_WORKSPACE_LIFECYCLE_EVENTS,
|
|
172
178
|
IPC_CAPABILITY_TAB_TAIL,
|
|
173
179
|
IPC_CAPABILITY_TURN_LIFECYCLE,
|
|
174
180
|
IPC_CAPABILITY_QUESTION_EVENTS,
|
|
@@ -209,15 +215,15 @@ export interface ProtocolHelloResult {
|
|
|
209
215
|
|
|
210
216
|
export interface AttachRequest {
|
|
211
217
|
protocolVersion: number
|
|
212
|
-
|
|
218
|
+
projectId: string
|
|
213
219
|
cols: number
|
|
214
220
|
rows: number
|
|
215
|
-
|
|
221
|
+
projectSnapshot?: ProjectSnapshotV1
|
|
216
222
|
/**
|
|
217
223
|
* v11 / capability `thinAttach`. When true, the daemon does not call
|
|
218
|
-
* `manager.resize` on the
|
|
224
|
+
* `manager.resize` on the project — the headless attacher (CLI) does not
|
|
219
225
|
* own a viewport, so it must not clobber the dimensions a UI process is
|
|
220
|
-
* driving for the same
|
|
226
|
+
* driving for the same project.
|
|
221
227
|
*
|
|
222
228
|
* Pre-v11 daemons ignore the field; the gate exists so the client knows
|
|
223
229
|
* to fall through to a full attach (with a sentinel size) when the daemon
|
|
@@ -229,7 +235,7 @@ export interface AttachRequest {
|
|
|
229
235
|
/**
|
|
230
236
|
* Slim per-tab summary returned by `listTabs`. Subset of {@link TabSession}
|
|
231
237
|
* with the buffer/viewport/terminalModes intentionally omitted so the request
|
|
232
|
-
* stays cheap even on
|
|
238
|
+
* stays cheap even on projects with many tabs.
|
|
233
239
|
*/
|
|
234
240
|
export interface TabSessionSummary {
|
|
235
241
|
id: string
|
|
@@ -238,7 +244,7 @@ export interface TabSessionSummary {
|
|
|
238
244
|
status: TabStatus
|
|
239
245
|
activity?: TabActivity
|
|
240
246
|
command: string
|
|
241
|
-
|
|
247
|
+
workspaceId?: string
|
|
242
248
|
workerName?: string
|
|
243
249
|
/**
|
|
244
250
|
* v13 / capability `listTabsLastLine`. The tab's last non-blank rendered
|
|
@@ -258,12 +264,12 @@ export interface AttachResult {
|
|
|
258
264
|
tabs: TabSession[]
|
|
259
265
|
activeTabId: string | null
|
|
260
266
|
/**
|
|
261
|
-
* Snapshot of every known
|
|
262
|
-
* the client atomically with `hydrate-
|
|
267
|
+
* Snapshot of every known project's status at attach time. Applied by
|
|
268
|
+
* the client atomically with `hydrate-project` so chips render the
|
|
263
269
|
* right state immediately, without the per-event race where a separate
|
|
264
|
-
* `
|
|
270
|
+
* `projectStatus` event could arrive before the project was in state.
|
|
265
271
|
*/
|
|
266
|
-
|
|
272
|
+
initialProjectStatuses: { projectId: string; status: ProjectStatus }[]
|
|
267
273
|
}
|
|
268
274
|
|
|
269
275
|
export type ClientRequest =
|
|
@@ -282,14 +288,14 @@ export type ClientRequest =
|
|
|
282
288
|
rows: number
|
|
283
289
|
cwd?: string
|
|
284
290
|
/**
|
|
285
|
-
* v11 / capability `
|
|
286
|
-
* inside a specific
|
|
291
|
+
* v11 / capability `createTabWorkspaceId`. Lets the CLI spawn a tab
|
|
292
|
+
* inside a specific workspace so the UI groups it correctly. The
|
|
287
293
|
* field is parsed unconditionally — older daemons accepted no such
|
|
288
294
|
* field, so this is a true additive on the wire — but the daemon
|
|
289
295
|
* only forwards it to the TM when its own capability is in play.
|
|
290
296
|
*/
|
|
291
|
-
|
|
292
|
-
/** v15 / capability `workerMetadata`: stable
|
|
297
|
+
workspaceId?: string
|
|
298
|
+
/** v15 / capability `workerMetadata`: stable project-scoped handle. */
|
|
293
299
|
workerName?: string
|
|
294
300
|
/** True only when the creator did not provide an explicit title. */
|
|
295
301
|
autoRenameCandidate?: boolean
|
|
@@ -318,51 +324,51 @@ export type ClientRequest =
|
|
|
318
324
|
// spawned successor binary can bind the canonical socket path while the
|
|
319
325
|
// terminal-manager (and every PTY) keeps running.
|
|
320
326
|
| { id: string; type: 'prepareReexec'; payload: { reason?: string } }
|
|
321
|
-
// Capability-gated on `listTabs`. Read-only enumeration of a
|
|
322
|
-
// tabs — does NOT attach. Lets a headless CLI inspect a
|
|
327
|
+
// Capability-gated on `listTabs`. Read-only enumeration of a project's
|
|
328
|
+
// tabs — does NOT attach. Lets a headless CLI inspect a project without
|
|
323
329
|
// implicit `manager.resize` or `setBroadcastEnabled` side effects.
|
|
324
|
-
| { id: string; type: 'listTabs'; payload: {
|
|
325
|
-
// v12 / capability `
|
|
326
|
-
//
|
|
327
|
-
// broadcasts `
|
|
328
|
-
// create (owning the live
|
|
330
|
+
| { id: string; type: 'listTabs'; payload: { projectId: string } }
|
|
331
|
+
// v12 / capability `projectLifecycle`. Ask the daemon to create a new
|
|
332
|
+
// project in the catalog. When any UI socket is attached the daemon
|
|
333
|
+
// broadcasts `projectCreateRequested` so the UI's reducer performs the
|
|
334
|
+
// create (owning the live project snapshot); when no UI is attached the
|
|
329
335
|
// daemon writes the catalog directly.
|
|
330
336
|
| {
|
|
331
337
|
id: string
|
|
332
|
-
type: '
|
|
338
|
+
type: 'createProject'
|
|
333
339
|
payload: { name: string; projectPath?: string; switch?: boolean }
|
|
334
340
|
}
|
|
335
|
-
// v12 / capability `
|
|
336
|
-
// another
|
|
341
|
+
// v12 / capability `projectLifecycle`. Ask the daemon to switch to
|
|
342
|
+
// another project. Broadcast → `projectSwitchRequested`; headless
|
|
337
343
|
// path bumps `lastOpenedAt` on the target so the next UI boot picks it.
|
|
338
|
-
| { id: string; type: '
|
|
339
|
-
// v12 / capability `
|
|
340
|
-
//
|
|
344
|
+
| { id: string; type: 'switchProject'; payload: { targetProjectId: string } }
|
|
345
|
+
// v12 / capability `projectLifecycle`. Ask the daemon to remove a
|
|
346
|
+
// project. Broadcast → `projectCloseRequested`; headless deletes the
|
|
341
347
|
// catalog entry directly.
|
|
342
348
|
| {
|
|
343
349
|
id: string
|
|
344
|
-
type: '
|
|
345
|
-
payload: {
|
|
350
|
+
type: 'closeProject'
|
|
351
|
+
payload: { targetProjectId: string }
|
|
346
352
|
}
|
|
347
|
-
// v12 / capability `
|
|
348
|
-
// `
|
|
349
|
-
// `
|
|
350
|
-
| { id: string; type: '
|
|
351
|
-
// v12 / capability `
|
|
352
|
-
// a
|
|
353
|
+
// v12 / capability `projectLifecycle`. UI announces that its own
|
|
354
|
+
// `handleSwitchProjectEffect` has finished; the daemon relays as a
|
|
355
|
+
// `projectSwitched` broadcast so a `--wait`ing CLI can exit.
|
|
356
|
+
| { id: string; type: 'announceProjectSwitched'; payload: { projectId: string } }
|
|
357
|
+
// v12 / capability `workspaceLifecycleEvents`. Append a workspace record to
|
|
358
|
+
// a project in the catalog. UI-attached path relays as `workspaceAdded`;
|
|
353
359
|
// headless path writes the catalog directly.
|
|
354
360
|
| {
|
|
355
361
|
id: string
|
|
356
|
-
type: '
|
|
357
|
-
payload: {
|
|
362
|
+
type: 'addWorkspaceRecord'
|
|
363
|
+
payload: { projectId: string; workspace: WorkspaceRecord }
|
|
358
364
|
}
|
|
359
|
-
// v12 / capability `
|
|
360
|
-
// UI-attached path relays as `
|
|
365
|
+
// v12 / capability `workspaceLifecycleEvents`. Remove a workspace record.
|
|
366
|
+
// UI-attached path relays as `workspaceRemoved`; headless path writes the
|
|
361
367
|
// catalog directly.
|
|
362
368
|
| {
|
|
363
369
|
id: string
|
|
364
|
-
type: '
|
|
365
|
-
payload: {
|
|
370
|
+
type: 'removeWorkspaceRecord'
|
|
371
|
+
payload: { projectId: string; workspaceId: string }
|
|
366
372
|
}
|
|
367
373
|
|
|
368
374
|
export type ServerResponse =
|
|
@@ -390,13 +396,22 @@ export type ServerEvent =
|
|
|
390
396
|
}
|
|
391
397
|
| { type: 'tabExit'; payload: { tabId: string; exitCode: number } }
|
|
392
398
|
| { type: 'tabError'; payload: { tabId: string; message: string } }
|
|
393
|
-
|
|
399
|
+
// v18: `workspaceId` is the tab's workspace when the daemon knows one. A
|
|
400
|
+
// client only holds tabs for the project it is attached to, so this is the
|
|
401
|
+
// only way it can attribute a *foreign* project's tab to a workspace row.
|
|
402
|
+
| {
|
|
403
|
+
type: 'tabStatus'
|
|
404
|
+
payload: { projectId: string; tabId: string; status: TabActivity; workspaceId?: string }
|
|
405
|
+
}
|
|
394
406
|
// v13 / capability `turnLifecycle`. Authoritative end-of-turn: broadcast
|
|
395
407
|
// once a tab's `idle` activity has held continuously for the settle window.
|
|
396
408
|
// Edge-triggered — re-armed only after the tab leaves `idle` again — so a
|
|
397
409
|
// driver gets exactly one per turn. `idleMs` is how long idle had held when
|
|
398
410
|
// the event fired.
|
|
399
|
-
| {
|
|
411
|
+
| {
|
|
412
|
+
type: 'tabTurnComplete'
|
|
413
|
+
payload: { projectId: string; tabId: string; idleMs: number; workspaceId?: string }
|
|
414
|
+
}
|
|
400
415
|
// v13 / capability `questionEvents`. Broadcast when a tab transitions into
|
|
401
416
|
// `waiting-input`. `prompt` is the captured tail text (authoritative);
|
|
402
417
|
// `options` is a best-effort per-CLI parse of the choice list and may be
|
|
@@ -404,73 +419,73 @@ export type ServerEvent =
|
|
|
404
419
|
| {
|
|
405
420
|
type: 'tabQuestion'
|
|
406
421
|
payload: {
|
|
407
|
-
|
|
422
|
+
projectId: string
|
|
408
423
|
tabId: string
|
|
409
424
|
kind: QuestionKind
|
|
410
425
|
prompt: string
|
|
411
426
|
options?: string[]
|
|
412
427
|
}
|
|
413
428
|
}
|
|
414
|
-
| { type: '
|
|
429
|
+
| { type: 'projectStatus'; payload: { projectId: string; status: ProjectStatus } }
|
|
415
430
|
// Capability-gated on `tabLifecycleEvents`. Broadcast after a successful
|
|
416
|
-
// `createTab` so every UI/CLI client attached to the same
|
|
431
|
+
// `createTab` so every UI/CLI client attached to the same project learns
|
|
417
432
|
// about the new tab without having to re-attach. The tab's `viewport` is
|
|
418
433
|
// intentionally omitted — the very next `tabRender` event carries it.
|
|
419
434
|
| {
|
|
420
435
|
type: 'tabAdded'
|
|
421
|
-
payload: {
|
|
436
|
+
payload: { projectId: string; tab: TabSession }
|
|
422
437
|
}
|
|
423
438
|
| {
|
|
424
439
|
type: 'tabMetadataUpdated'
|
|
425
440
|
payload: {
|
|
426
|
-
|
|
441
|
+
projectId: string
|
|
427
442
|
tabId: string
|
|
428
443
|
title?: string
|
|
429
444
|
autoRenameStatus?: 'eligible' | 'attempted'
|
|
430
445
|
}
|
|
431
446
|
}
|
|
432
|
-
// v12 / capability `
|
|
433
|
-
// CLI issues `
|
|
434
|
-
// create-
|
|
435
|
-
// Broadcast is NOT
|
|
436
|
-
//
|
|
447
|
+
// v12 / capability `projectLifecycle`. Broadcast to every socket when a
|
|
448
|
+
// CLI issues `createProject` while a UI is attached — the UI runs its
|
|
449
|
+
// create-project handler so the live project snapshot is preserved.
|
|
450
|
+
// Broadcast is NOT project-scoped; the UI may be attached to a different
|
|
451
|
+
// project than the one being created.
|
|
437
452
|
| {
|
|
438
|
-
type: '
|
|
453
|
+
type: 'projectCreateRequested'
|
|
439
454
|
payload: { name: string; projectPath?: string; switch?: boolean }
|
|
440
455
|
}
|
|
441
|
-
// v12 / capability `
|
|
442
|
-
// `
|
|
443
|
-
// `
|
|
456
|
+
// v12 / capability `projectLifecycle`. Broadcast when a CLI issues
|
|
457
|
+
// `switchProject`; UI runs `handleSwitchProjectEffect` and then emits
|
|
458
|
+
// `announceProjectSwitched` when done.
|
|
444
459
|
| {
|
|
445
|
-
type: '
|
|
446
|
-
payload: {
|
|
460
|
+
type: 'projectSwitchRequested'
|
|
461
|
+
payload: { targetProjectId: string }
|
|
447
462
|
}
|
|
448
|
-
// v12 / capability `
|
|
449
|
-
// `
|
|
463
|
+
// v12 / capability `projectLifecycle`. Broadcast when a CLI issues
|
|
464
|
+
// `closeProject`; UI runs `handleDeleteProjectEffect`.
|
|
450
465
|
| {
|
|
451
|
-
type: '
|
|
452
|
-
payload: {
|
|
466
|
+
type: 'projectCloseRequested'
|
|
467
|
+
payload: { targetProjectId: string }
|
|
453
468
|
}
|
|
454
|
-
// v12 / capability `
|
|
455
|
-
// `
|
|
469
|
+
// v12 / capability `projectLifecycle`. Daemon relay of the UI's
|
|
470
|
+
// `announceProjectSwitched` so a `--wait`ing CLI can exit.
|
|
456
471
|
| {
|
|
457
|
-
type: '
|
|
458
|
-
payload: {
|
|
472
|
+
type: 'projectSwitched'
|
|
473
|
+
payload: { projectId: string }
|
|
459
474
|
}
|
|
460
|
-
// v12 / capability `
|
|
461
|
-
// `
|
|
475
|
+
// v12 / capability `workspaceLifecycleEvents`. Broadcast after a CLI
|
|
476
|
+
// `addWorkspaceRecord` while a UI is attached; the UI reducer appends the
|
|
462
477
|
// record and persists the catalog.
|
|
463
478
|
| {
|
|
464
|
-
type: '
|
|
465
|
-
payload: {
|
|
479
|
+
type: 'workspaceAdded'
|
|
480
|
+
payload: { projectId: string; workspace: WorkspaceRecord }
|
|
466
481
|
}
|
|
467
|
-
// v12 / capability `
|
|
468
|
-
// `
|
|
482
|
+
// v12 / capability `workspaceLifecycleEvents`. Broadcast after a CLI
|
|
483
|
+
// `removeWorkspaceRecord` while a UI is attached; the UI reducer removes
|
|
469
484
|
// the record (and closes any tabs pinned to it via the existing
|
|
470
|
-
//
|
|
485
|
+
// workspace-removal side-effect).
|
|
471
486
|
| {
|
|
472
|
-
type: '
|
|
473
|
-
payload: {
|
|
487
|
+
type: 'workspaceRemoved'
|
|
488
|
+
payload: { projectId: string; workspaceId: string }
|
|
474
489
|
}
|
|
475
490
|
|
|
476
491
|
export type IpcMessage = ClientRequest | ServerResponse | ServerEvent
|
|
@@ -516,7 +531,7 @@ function isTabActivity(value: unknown): value is TabActivity {
|
|
|
516
531
|
return value === 'working' || value === 'waiting-input' || value === 'idle'
|
|
517
532
|
}
|
|
518
533
|
|
|
519
|
-
function
|
|
534
|
+
function isProjectStatus(value: unknown): value is ProjectStatus {
|
|
520
535
|
return (
|
|
521
536
|
isObjectRecord(value) &&
|
|
522
537
|
typeof value.working === 'boolean' &&
|
|
@@ -608,7 +623,7 @@ function isTabSessionSummary(value: unknown): value is TabSessionSummary {
|
|
|
608
623
|
value.activity === 'waiting-input' ||
|
|
609
624
|
value.activity === 'idle') &&
|
|
610
625
|
isString(value.command) &&
|
|
611
|
-
(value.
|
|
626
|
+
(value.workspaceId === undefined || isString(value.workspaceId)) &&
|
|
612
627
|
(value.workerName === undefined || isString(value.workerName)) &&
|
|
613
628
|
(value.lastLine === undefined || isString(value.lastLine))
|
|
614
629
|
)
|
|
@@ -652,7 +667,7 @@ function isTabSession(value: unknown): value is TabSession {
|
|
|
652
667
|
(value.viewport === undefined || isTerminalSnapshot(value.viewport)) &&
|
|
653
668
|
(value.errorMessage === undefined || isString(value.errorMessage)) &&
|
|
654
669
|
(value.exitCode === undefined || isFiniteNumber(value.exitCode)) &&
|
|
655
|
-
(value.
|
|
670
|
+
(value.workspaceId === undefined || isString(value.workspaceId))
|
|
656
671
|
)
|
|
657
672
|
}
|
|
658
673
|
|
|
@@ -663,9 +678,9 @@ function isAttachResult(value: unknown): value is AttachResult {
|
|
|
663
678
|
Array.isArray(value.tabs) &&
|
|
664
679
|
value.tabs.every(isTabSession) &&
|
|
665
680
|
isNullableString(value.activeTabId) &&
|
|
666
|
-
Array.isArray(value.
|
|
667
|
-
value.
|
|
668
|
-
(entry) => isObjectRecord(entry) && isString(entry.
|
|
681
|
+
Array.isArray(value.initialProjectStatuses) &&
|
|
682
|
+
value.initialProjectStatuses.every(
|
|
683
|
+
(entry) => isObjectRecord(entry) && isString(entry.projectId) && isProjectStatus(entry.status)
|
|
669
684
|
)
|
|
670
685
|
)
|
|
671
686
|
}
|
|
@@ -717,13 +732,13 @@ export function parseClientRequest(value: unknown): ClientRequest {
|
|
|
717
732
|
isFiniteNumber(value.payload.protocolVersion),
|
|
718
733
|
'attach.protocolVersion must be a number'
|
|
719
734
|
)
|
|
720
|
-
assert(isString(value.payload.
|
|
735
|
+
assert(isString(value.payload.projectId), 'attach.projectId must be a string')
|
|
721
736
|
assert(isFiniteNumber(value.payload.cols), 'attach.cols must be a number')
|
|
722
737
|
assert(isFiniteNumber(value.payload.rows), 'attach.rows must be a number')
|
|
723
738
|
assert(
|
|
724
|
-
value.payload.
|
|
725
|
-
|
|
726
|
-
'attach.
|
|
739
|
+
value.payload.projectSnapshot === undefined ||
|
|
740
|
+
isProjectSnapshotV1(value.payload.projectSnapshot),
|
|
741
|
+
'attach.projectSnapshot must be a valid project snapshot'
|
|
727
742
|
)
|
|
728
743
|
assert(
|
|
729
744
|
value.payload.thin === undefined || typeof value.payload.thin === 'boolean',
|
|
@@ -731,7 +746,7 @@ export function parseClientRequest(value: unknown): ClientRequest {
|
|
|
731
746
|
)
|
|
732
747
|
return value as ClientRequest
|
|
733
748
|
case 'listTabs':
|
|
734
|
-
assert(isString(value.payload.
|
|
749
|
+
assert(isString(value.payload.projectId), 'listTabs.projectId must be a string')
|
|
735
750
|
return value as ClientRequest
|
|
736
751
|
case 'createTab':
|
|
737
752
|
assert(isString(value.payload.tabId), 'createTab.tabId must be a string')
|
|
@@ -752,8 +767,8 @@ export function parseClientRequest(value: unknown): ClientRequest {
|
|
|
752
767
|
'createTab.cwd must be a string'
|
|
753
768
|
)
|
|
754
769
|
assert(
|
|
755
|
-
value.payload.
|
|
756
|
-
'createTab.
|
|
770
|
+
value.payload.workspaceId === undefined || isString(value.payload.workspaceId),
|
|
771
|
+
'createTab.workspaceId must be a string when present'
|
|
757
772
|
)
|
|
758
773
|
assert(
|
|
759
774
|
value.payload.workerName === undefined || isString(value.payload.workerName),
|
|
@@ -807,48 +822,51 @@ export function parseClientRequest(value: unknown): ClientRequest {
|
|
|
807
822
|
'prepareReexec.reason must be a string when present'
|
|
808
823
|
)
|
|
809
824
|
return value as ClientRequest
|
|
810
|
-
case '
|
|
825
|
+
case 'createProject':
|
|
811
826
|
assert(
|
|
812
827
|
isString(value.payload.name) && value.payload.name.length > 0,
|
|
813
|
-
'
|
|
828
|
+
'createProject.name must be a non-empty string'
|
|
814
829
|
)
|
|
815
830
|
assert(
|
|
816
831
|
value.payload.projectPath === undefined || isString(value.payload.projectPath),
|
|
817
|
-
'
|
|
832
|
+
'createProject.projectPath must be a string when present'
|
|
818
833
|
)
|
|
819
834
|
assert(
|
|
820
835
|
value.payload.switch === undefined || typeof value.payload.switch === 'boolean',
|
|
821
|
-
'
|
|
836
|
+
'createProject.switch must be a boolean when present'
|
|
822
837
|
)
|
|
823
838
|
return value as ClientRequest
|
|
824
|
-
case '
|
|
839
|
+
case 'switchProject':
|
|
825
840
|
assert(
|
|
826
|
-
isString(value.payload.
|
|
827
|
-
'
|
|
841
|
+
isString(value.payload.targetProjectId),
|
|
842
|
+
'switchProject.targetProjectId must be a string'
|
|
828
843
|
)
|
|
829
844
|
return value as ClientRequest
|
|
830
|
-
case '
|
|
845
|
+
case 'closeProject':
|
|
831
846
|
assert(
|
|
832
|
-
isString(value.payload.
|
|
833
|
-
'
|
|
847
|
+
isString(value.payload.targetProjectId),
|
|
848
|
+
'closeProject.targetProjectId must be a string'
|
|
834
849
|
)
|
|
835
850
|
return value as ClientRequest
|
|
836
|
-
case '
|
|
851
|
+
case 'announceProjectSwitched':
|
|
837
852
|
assert(
|
|
838
|
-
isString(value.payload.
|
|
839
|
-
'
|
|
853
|
+
isString(value.payload.projectId),
|
|
854
|
+
'announceProjectSwitched.projectId must be a string'
|
|
840
855
|
)
|
|
841
856
|
return value as ClientRequest
|
|
842
|
-
case '
|
|
843
|
-
assert(isString(value.payload.
|
|
857
|
+
case 'addWorkspaceRecord':
|
|
858
|
+
assert(isString(value.payload.projectId), 'addWorkspaceRecord.projectId must be a string')
|
|
844
859
|
assert(
|
|
845
|
-
|
|
846
|
-
'
|
|
860
|
+
isWorkspaceRecord(value.payload.workspace),
|
|
861
|
+
'addWorkspaceRecord.workspace must be a WorkspaceRecord'
|
|
847
862
|
)
|
|
848
863
|
return value as ClientRequest
|
|
849
|
-
case '
|
|
850
|
-
assert(isString(value.payload.
|
|
851
|
-
assert(
|
|
864
|
+
case 'removeWorkspaceRecord':
|
|
865
|
+
assert(isString(value.payload.projectId), 'removeWorkspaceRecord.projectId must be a string')
|
|
866
|
+
assert(
|
|
867
|
+
isString(value.payload.workspaceId),
|
|
868
|
+
'removeWorkspaceRecord.workspaceId must be a string'
|
|
869
|
+
)
|
|
852
870
|
return value as ClientRequest
|
|
853
871
|
default:
|
|
854
872
|
throw new IpcProtocolError(`Unknown IPC request type: ${String(value.type)}`)
|
|
@@ -906,17 +924,25 @@ export function parseServerMessage(value: unknown): ServerResponse | ServerEvent
|
|
|
906
924
|
assert(isString(value.payload.message), 'tabError.message must be a string')
|
|
907
925
|
return value as ServerEvent
|
|
908
926
|
case 'tabStatus':
|
|
909
|
-
assert(isString(value.payload.
|
|
927
|
+
assert(isString(value.payload.projectId), 'tabStatus.projectId must be a string')
|
|
910
928
|
assert(isString(value.payload.tabId), 'tabStatus.tabId must be a string')
|
|
911
929
|
assert(isTabActivity(value.payload.status), 'tabStatus.status is invalid')
|
|
930
|
+
assert(
|
|
931
|
+
value.payload.workspaceId === undefined || isString(value.payload.workspaceId),
|
|
932
|
+
'tabStatus.workspaceId must be a string when present'
|
|
933
|
+
)
|
|
912
934
|
return value as ServerEvent
|
|
913
935
|
case 'tabTurnComplete':
|
|
914
|
-
assert(isString(value.payload.
|
|
936
|
+
assert(isString(value.payload.projectId), 'tabTurnComplete.projectId must be a string')
|
|
915
937
|
assert(isString(value.payload.tabId), 'tabTurnComplete.tabId must be a string')
|
|
916
938
|
assert(isFiniteNumber(value.payload.idleMs), 'tabTurnComplete.idleMs must be a number')
|
|
939
|
+
assert(
|
|
940
|
+
value.payload.workspaceId === undefined || isString(value.payload.workspaceId),
|
|
941
|
+
'tabTurnComplete.workspaceId must be a string when present'
|
|
942
|
+
)
|
|
917
943
|
return value as ServerEvent
|
|
918
944
|
case 'tabQuestion':
|
|
919
|
-
assert(isString(value.payload.
|
|
945
|
+
assert(isString(value.payload.projectId), 'tabQuestion.projectId must be a string')
|
|
920
946
|
assert(isString(value.payload.tabId), 'tabQuestion.tabId must be a string')
|
|
921
947
|
assert(isQuestionKind(value.payload.kind), 'tabQuestion.kind is invalid')
|
|
922
948
|
assert(isString(value.payload.prompt), 'tabQuestion.prompt must be a string')
|
|
@@ -926,11 +952,11 @@ export function parseServerMessage(value: unknown): ServerResponse | ServerEvent
|
|
|
926
952
|
)
|
|
927
953
|
return value as ServerEvent
|
|
928
954
|
case 'tabAdded':
|
|
929
|
-
assert(isString(value.payload.
|
|
955
|
+
assert(isString(value.payload.projectId), 'tabAdded.projectId must be a string')
|
|
930
956
|
assert(isTabSession(value.payload.tab), 'tabAdded.tab is invalid')
|
|
931
957
|
return value as ServerEvent
|
|
932
958
|
case 'tabMetadataUpdated':
|
|
933
|
-
assert(isString(value.payload.
|
|
959
|
+
assert(isString(value.payload.projectId), 'tabMetadataUpdated.projectId must be a string')
|
|
934
960
|
assert(isString(value.payload.tabId), 'tabMetadataUpdated.tabId must be a string')
|
|
935
961
|
assert(
|
|
936
962
|
value.payload.title === undefined || isString(value.payload.title),
|
|
@@ -943,49 +969,49 @@ export function parseServerMessage(value: unknown): ServerResponse | ServerEvent
|
|
|
943
969
|
'tabMetadataUpdated.autoRenameStatus is invalid'
|
|
944
970
|
)
|
|
945
971
|
return value as ServerEvent
|
|
946
|
-
case '
|
|
947
|
-
assert(isString(value.payload.
|
|
948
|
-
assert(
|
|
972
|
+
case 'projectStatus':
|
|
973
|
+
assert(isString(value.payload.projectId), 'projectStatus.projectId must be a string')
|
|
974
|
+
assert(isProjectStatus(value.payload.status), 'projectStatus.status is invalid')
|
|
949
975
|
return value as ServerEvent
|
|
950
|
-
case '
|
|
976
|
+
case 'projectCreateRequested':
|
|
951
977
|
assert(
|
|
952
978
|
isString(value.payload.name) && value.payload.name.length > 0,
|
|
953
|
-
'
|
|
979
|
+
'projectCreateRequested.name must be a non-empty string'
|
|
954
980
|
)
|
|
955
981
|
assert(
|
|
956
982
|
value.payload.projectPath === undefined || isString(value.payload.projectPath),
|
|
957
|
-
'
|
|
983
|
+
'projectCreateRequested.projectPath must be a string when present'
|
|
958
984
|
)
|
|
959
985
|
assert(
|
|
960
986
|
value.payload.switch === undefined || typeof value.payload.switch === 'boolean',
|
|
961
|
-
'
|
|
987
|
+
'projectCreateRequested.switch must be a boolean when present'
|
|
962
988
|
)
|
|
963
989
|
return value as ServerEvent
|
|
964
|
-
case '
|
|
990
|
+
case 'projectSwitchRequested':
|
|
965
991
|
assert(
|
|
966
|
-
isString(value.payload.
|
|
967
|
-
'
|
|
992
|
+
isString(value.payload.targetProjectId),
|
|
993
|
+
'projectSwitchRequested.targetProjectId must be a string'
|
|
968
994
|
)
|
|
969
995
|
return value as ServerEvent
|
|
970
|
-
case '
|
|
996
|
+
case 'projectCloseRequested':
|
|
971
997
|
assert(
|
|
972
|
-
isString(value.payload.
|
|
973
|
-
'
|
|
998
|
+
isString(value.payload.targetProjectId),
|
|
999
|
+
'projectCloseRequested.targetProjectId must be a string'
|
|
974
1000
|
)
|
|
975
1001
|
return value as ServerEvent
|
|
976
|
-
case '
|
|
977
|
-
assert(isString(value.payload.
|
|
1002
|
+
case 'projectSwitched':
|
|
1003
|
+
assert(isString(value.payload.projectId), 'projectSwitched.projectId must be a string')
|
|
978
1004
|
return value as ServerEvent
|
|
979
|
-
case '
|
|
980
|
-
assert(isString(value.payload.
|
|
1005
|
+
case 'workspaceAdded':
|
|
1006
|
+
assert(isString(value.payload.projectId), 'workspaceAdded.projectId must be a string')
|
|
981
1007
|
assert(
|
|
982
|
-
|
|
983
|
-
'
|
|
1008
|
+
isWorkspaceRecord(value.payload.workspace),
|
|
1009
|
+
'workspaceAdded.workspace must be a WorkspaceRecord'
|
|
984
1010
|
)
|
|
985
1011
|
return value as ServerEvent
|
|
986
|
-
case '
|
|
987
|
-
assert(isString(value.payload.
|
|
988
|
-
assert(isString(value.payload.
|
|
1012
|
+
case 'workspaceRemoved':
|
|
1013
|
+
assert(isString(value.payload.projectId), 'workspaceRemoved.projectId must be a string')
|
|
1014
|
+
assert(isString(value.payload.workspaceId), 'workspaceRemoved.workspaceId must be a string')
|
|
989
1015
|
return value as ServerEvent
|
|
990
1016
|
default:
|
|
991
1017
|
throw new IpcProtocolError(`Unknown IPC response type: ${String(value.type)}`)
|