@brimveyn/aimux 1.20.4 → 1.22.0
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 +305 -1589
- package/src/app-runtime/snippet-actions.ts +3 -2
- package/src/app-runtime/split-drag-controller.ts +4 -8
- 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 +28 -42
- 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 +28 -33
- 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 +102 -85
- 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 +149 -101
- 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-merge.ts +64 -0
- package/src/git/pr-status-poller.ts +57 -0
- package/src/git/pr-status.ts +227 -0
- 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 +11 -6
- 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/open-url.ts +39 -0
- 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 +3 -1
- 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 +75 -0
- package/src/state/dispatch-ref.ts +1 -1
- package/src/state/git-pane-sizing.ts +0 -9
- package/src/state/layout-resize.ts +2 -2
- package/src/state/pr-status-store.ts +39 -0
- 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} +77 -73
- 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 -53
- 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 +86 -15
- package/src/state/selectors.ts +49 -37
- package/src/state/store.ts +83 -57
- package/src/state/types.ts +261 -417
- 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/diff-renderer/pierre-diff.tsx +2 -1
- 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-header.tsx +105 -39
- package/src/ui/components/git/pane/git-pane-widget.tsx +37 -23
- package/src/ui/components/git/pane/pr-checks-panel.tsx +197 -0
- package/src/ui/components/git/pane/pr-state-row.tsx +103 -0
- package/src/ui/components/layout/bar.tsx +191 -0
- 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 +48 -37
- 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 +164 -230
- 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 +21 -0
- package/src/ui/widgets/widget-context-menu.ts +85 -0
- 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 -45
- package/src/ui/components/git/pane/git-pane-context-menu.ts +0 -26
- package/src/ui/components/layout/sidebar/sidebar.tsx +0 -163
- 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolve as resolvePath } from 'node:path'
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { WorkspaceRecord } from '../../../state/types'
|
|
4
4
|
import type { CliContext } from '../../context'
|
|
5
5
|
import type { CliCommand } from '../../registry'
|
|
6
6
|
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from '../../../pty/command-registry'
|
|
23
23
|
import { CliUsageError, SHARED_FLAGS } from '../../flags'
|
|
24
24
|
import { EXIT_OK, writeJson } from '../../output'
|
|
25
|
-
import {
|
|
25
|
+
import { createProjectWorkspace } from '../workspace/create-core'
|
|
26
26
|
|
|
27
27
|
const FALLBACK_COLS = 200
|
|
28
28
|
const FALLBACK_ROWS = 60
|
|
@@ -35,10 +35,10 @@ export interface CreateCliTabOptions {
|
|
|
35
35
|
cwd?: string
|
|
36
36
|
effort?: string
|
|
37
37
|
model?: string
|
|
38
|
-
|
|
38
|
+
newWorkspace?: boolean | string
|
|
39
39
|
title?: string
|
|
40
40
|
workerName?: string
|
|
41
|
-
|
|
41
|
+
workspaceId?: string
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export interface CreateCliTabResult {
|
|
@@ -53,26 +53,26 @@ export interface CreateCliTabResult {
|
|
|
53
53
|
tabId: string
|
|
54
54
|
title: string
|
|
55
55
|
workerName: string | null
|
|
56
|
-
|
|
56
|
+
workspaceId: string | null
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Resolve the cwd a spawned tab should run in. Precedence: explicit `--cwd`
|
|
61
|
-
* (resolved to absolute) > the resolved
|
|
62
|
-
* daemon's default).
|
|
61
|
+
* (resolved to absolute) > the resolved workspace's path > undefined (the
|
|
62
|
+
* daemon's default). Workspace record paths are already absolute.
|
|
63
63
|
*/
|
|
64
64
|
export function resolveTabCwd(
|
|
65
65
|
cwdFlag: string | undefined,
|
|
66
|
-
|
|
66
|
+
workspaceRecord: { path: string } | undefined
|
|
67
67
|
): string | undefined {
|
|
68
68
|
if (cwdFlag !== undefined) return resolvePath(cwdFlag)
|
|
69
|
-
return
|
|
69
|
+
return workspaceRecord?.path
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Resolve the base command a tab launches. Mirrors the UI's precedence
|
|
74
74
|
* (`src/app-runtime/side-effects.ts`): an explicit `--command` override wins,
|
|
75
|
-
* else the
|
|
75
|
+
* else the project's persisted `customCommands[assistantId]` (so CLI workers
|
|
76
76
|
* inherit e.g. `claude --dangerously-skip-permissions`), else the builtin
|
|
77
77
|
* default. `getAllAssistantOptions` deliberately does NOT apply builtin
|
|
78
78
|
* overrides, so this lookup must be explicit.
|
|
@@ -85,13 +85,13 @@ export function resolveAssistantCommand(
|
|
|
85
85
|
return commandOverride ?? customCommands[option.id] ?? option.command
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
async function
|
|
89
|
-
record:
|
|
88
|
+
async function rollbackCreatedWorkspace(
|
|
89
|
+
record: WorkspaceRecord,
|
|
90
90
|
ctx: CliContext,
|
|
91
91
|
originalError: unknown
|
|
92
92
|
): Promise<never> {
|
|
93
93
|
const daemon = await ctx.getDaemon()
|
|
94
|
-
const
|
|
94
|
+
const project = ctx.getProject()
|
|
95
95
|
let rollbackError: unknown
|
|
96
96
|
try {
|
|
97
97
|
await removeGitWorktree({
|
|
@@ -100,9 +100,9 @@ async function rollbackCreatedWorktree(
|
|
|
100
100
|
targetPath: record.path,
|
|
101
101
|
})
|
|
102
102
|
await pruneEmptyWorktreeParent(record.path)
|
|
103
|
-
await daemon.expectOk('
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
await daemon.expectOk('removeWorkspaceRecord', {
|
|
104
|
+
projectId: project.id,
|
|
105
|
+
workspaceId: record.id,
|
|
106
106
|
})
|
|
107
107
|
} catch (error) {
|
|
108
108
|
rollbackError = error
|
|
@@ -117,8 +117,8 @@ async function rollbackCreatedWorktree(
|
|
|
117
117
|
/**
|
|
118
118
|
* Create a tab without writing to stdout. Worker commands compose this helper
|
|
119
119
|
* with prompt dispatch/await while `tab create` remains a thin compatibility
|
|
120
|
-
* adapter. All validation and daemon attachment happen before a
|
|
121
|
-
* created; any later failure rolls the fresh
|
|
120
|
+
* adapter. All validation and daemon attachment happen before a workspace is
|
|
121
|
+
* created; any later failure rolls the fresh workspace back.
|
|
122
122
|
*/
|
|
123
123
|
export async function createCliTab(
|
|
124
124
|
ctx: CliContext,
|
|
@@ -132,10 +132,10 @@ export async function createCliTab(
|
|
|
132
132
|
cwd: cwdRaw,
|
|
133
133
|
effort,
|
|
134
134
|
model,
|
|
135
|
-
|
|
135
|
+
newWorkspace,
|
|
136
136
|
title: requestedTitle,
|
|
137
137
|
workerName,
|
|
138
|
-
|
|
138
|
+
workspaceId: requestedWorkspaceId,
|
|
139
139
|
} = options
|
|
140
140
|
if (assistantId.length === 0) throw new CliUsageError('--assistant is required')
|
|
141
141
|
if (workerName !== undefined && workerName.trim().length === 0) {
|
|
@@ -147,18 +147,18 @@ export async function createCliTab(
|
|
|
147
147
|
)
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
150
|
+
const createFreshWorkspace = newWorkspace !== undefined && newWorkspace !== false
|
|
151
|
+
if (createFreshWorkspace && requestedWorkspaceId !== undefined) {
|
|
152
152
|
throw new CliUsageError(
|
|
153
|
-
'--new-
|
|
153
|
+
'--new-workspace creates its own; use --workspace <id> to co-locate instead'
|
|
154
154
|
)
|
|
155
155
|
}
|
|
156
|
-
if (
|
|
157
|
-
throw new CliUsageError('--new-
|
|
156
|
+
if (createFreshWorkspace && cwdRaw !== undefined) {
|
|
157
|
+
throw new CliUsageError('--new-workspace sets the cwd to the new workspace; drop --cwd')
|
|
158
158
|
}
|
|
159
|
-
if (!
|
|
159
|
+
if (!createFreshWorkspace && (base !== undefined || branch !== undefined)) {
|
|
160
160
|
throw new CliUsageError(
|
|
161
|
-
'--base / --branch require --new-
|
|
161
|
+
'--base / --branch require --new-workspace (use `workspace create` otherwise)'
|
|
162
162
|
)
|
|
163
163
|
}
|
|
164
164
|
|
|
@@ -177,7 +177,7 @@ export async function createCliTab(
|
|
|
177
177
|
const title = requestedTitle ?? option.label
|
|
178
178
|
const tabId = createPrefixedId('tab')
|
|
179
179
|
|
|
180
|
-
const
|
|
180
|
+
const project = ctx.getProject()
|
|
181
181
|
const daemon = await ctx.getDaemon()
|
|
182
182
|
if (!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH)) {
|
|
183
183
|
throw new Error(
|
|
@@ -193,44 +193,44 @@ export async function createCliTab(
|
|
|
193
193
|
if (!daemon.hasCapability(IPC_CAPABILITY_LIST_TABS)) {
|
|
194
194
|
throw new Error('daemon cannot validate worker-name uniqueness — restart aimux')
|
|
195
195
|
}
|
|
196
|
-
const existing = await daemon.listTabs(
|
|
196
|
+
const existing = await daemon.listTabs(project.id)
|
|
197
197
|
if (existing.tabs.some((tab) => tab.workerName === workerName)) {
|
|
198
|
-
throw new Error(`worker name already exists in
|
|
198
|
+
throw new Error(`worker name already exists in project "${project.name}": ${workerName}`)
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
// Attach before creating a
|
|
202
|
+
// Attach before creating a workspace so stale daemon/project failures have no
|
|
203
203
|
// git-side effect.
|
|
204
|
-
await daemon.attach({ cols: 0,
|
|
204
|
+
await daemon.attach({ cols: 0, projectId: project.id, rows: 0, thin: true })
|
|
205
205
|
|
|
206
|
-
let
|
|
207
|
-
let
|
|
208
|
-
|
|
209
|
-
?
|
|
206
|
+
let workspaceId = requestedWorkspaceId ?? project.activeWorkspaceId
|
|
207
|
+
let workspaceRecord =
|
|
208
|
+
workspaceId !== undefined
|
|
209
|
+
? project.workspaces?.find((entry) => entry.id === workspaceId)
|
|
210
210
|
: undefined
|
|
211
|
-
if (
|
|
212
|
-
const ids =
|
|
213
|
-
throw new Error(`unknown
|
|
211
|
+
if (requestedWorkspaceId !== undefined && workspaceRecord === undefined) {
|
|
212
|
+
const ids = project.workspaces?.map((entry) => entry.id).join(', ') ?? '(none)'
|
|
213
|
+
throw new Error(`unknown workspace id: ${requestedWorkspaceId} (known: ${ids})`)
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
let
|
|
217
|
-
if (
|
|
218
|
-
const
|
|
219
|
-
typeof
|
|
220
|
-
?
|
|
216
|
+
let createdWorkspace: WorkspaceRecord | undefined
|
|
217
|
+
if (createFreshWorkspace) {
|
|
218
|
+
const workspaceName =
|
|
219
|
+
typeof newWorkspace === 'string' && newWorkspace !== ''
|
|
220
|
+
? newWorkspace
|
|
221
221
|
: `${assistantId}-${tabId.slice(-6)}`
|
|
222
|
-
|
|
222
|
+
createdWorkspace = await createProjectWorkspace({
|
|
223
223
|
base: base ?? 'HEAD',
|
|
224
|
-
branch: branch ?? `aimux/${
|
|
224
|
+
branch: branch ?? `aimux/${workspaceName}`,
|
|
225
225
|
daemon,
|
|
226
|
-
name:
|
|
227
|
-
|
|
226
|
+
name: workspaceName,
|
|
227
|
+
project,
|
|
228
228
|
})
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
workspaceId = createdWorkspace.id
|
|
230
|
+
workspaceRecord = createdWorkspace
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
const cwd = resolveTabCwd(cwdRaw,
|
|
233
|
+
const cwd = resolveTabCwd(cwdRaw, workspaceRecord)
|
|
234
234
|
const useFallback = daemon.hasCapability(IPC_CAPABILITY_CREATE_TAB_SIZE_FALLBACK)
|
|
235
235
|
try {
|
|
236
236
|
await daemon.expectOk('createTab', {
|
|
@@ -244,28 +244,28 @@ export async function createCliTab(
|
|
|
244
244
|
tabId,
|
|
245
245
|
title,
|
|
246
246
|
workerName,
|
|
247
|
-
|
|
247
|
+
workspaceId,
|
|
248
248
|
})
|
|
249
249
|
} catch (error) {
|
|
250
|
-
if (
|
|
251
|
-
return
|
|
250
|
+
if (createdWorkspace !== undefined) {
|
|
251
|
+
return rollbackCreatedWorkspace(createdWorkspace, ctx, error)
|
|
252
252
|
}
|
|
253
253
|
throw error
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
return {
|
|
257
257
|
assistant: assistantId,
|
|
258
|
-
branch:
|
|
258
|
+
branch: workspaceRecord?.branch ?? null,
|
|
259
259
|
command: [executable, ...args].join(' '),
|
|
260
260
|
cwd: cwd ?? null,
|
|
261
261
|
effort: effort ?? null,
|
|
262
262
|
model: model ?? null,
|
|
263
|
-
name:
|
|
264
|
-
path:
|
|
263
|
+
name: workspaceRecord?.name ?? null,
|
|
264
|
+
path: workspaceRecord?.path ?? null,
|
|
265
265
|
tabId,
|
|
266
266
|
title,
|
|
267
267
|
workerName: workerName ?? null,
|
|
268
|
-
|
|
268
|
+
workspaceId: workspaceId ?? null,
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
@@ -310,26 +310,27 @@ export const tabCreate: CliCommand = {
|
|
|
310
310
|
name: 'effort',
|
|
311
311
|
},
|
|
312
312
|
{
|
|
313
|
-
complete: { kind: 'dynamic', source: '
|
|
314
|
-
description: '
|
|
313
|
+
complete: { kind: 'dynamic', source: 'workspace' },
|
|
314
|
+
description: 'workspace id the tab belongs to (defaults to the project’s active workspace)',
|
|
315
315
|
kind: 'string',
|
|
316
|
-
name: '
|
|
316
|
+
name: 'workspace',
|
|
317
317
|
},
|
|
318
318
|
{
|
|
319
319
|
complete: { kind: 'none' },
|
|
320
|
-
description:
|
|
320
|
+
description:
|
|
321
|
+
'create a fresh workspace for this tab (optionally named: --new-workspace=<name>)',
|
|
321
322
|
kind: 'optional-string',
|
|
322
|
-
name: 'new-
|
|
323
|
+
name: 'new-workspace',
|
|
323
324
|
},
|
|
324
325
|
{
|
|
325
326
|
complete: { kind: 'dynamic', source: 'git-ref' },
|
|
326
|
-
description: 'base ref for --new-
|
|
327
|
+
description: 'base ref for --new-workspace (default HEAD)',
|
|
327
328
|
kind: 'string',
|
|
328
329
|
name: 'base',
|
|
329
330
|
},
|
|
330
331
|
{
|
|
331
332
|
complete: { kind: 'none' },
|
|
332
|
-
description: 'branch for --new-
|
|
333
|
+
description: 'branch for --new-workspace (default aimux/<name>)',
|
|
333
334
|
kind: 'string',
|
|
334
335
|
name: 'branch',
|
|
335
336
|
},
|
|
@@ -347,13 +348,13 @@ export const tabCreate: CliCommand = {
|
|
|
347
348
|
|
|
348
349
|
const title = typeof ctx.args.flags.title === 'string' ? ctx.args.flags.title : undefined
|
|
349
350
|
const cwdRaw = typeof ctx.args.flags.cwd === 'string' ? ctx.args.flags.cwd : undefined
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
typeof
|
|
353
|
-
?
|
|
351
|
+
const newWorkspaceRaw = ctx.args.flags['new-workspace']
|
|
352
|
+
const newWorkspaceFlag =
|
|
353
|
+
typeof newWorkspaceRaw === 'string' || typeof newWorkspaceRaw === 'boolean'
|
|
354
|
+
? newWorkspaceRaw
|
|
354
355
|
: undefined
|
|
355
|
-
const
|
|
356
|
-
typeof ctx.args.flags.
|
|
356
|
+
const workspaceFlag =
|
|
357
|
+
typeof ctx.args.flags.workspace === 'string' ? ctx.args.flags.workspace : undefined
|
|
357
358
|
const baseFlag = typeof ctx.args.flags.base === 'string' ? ctx.args.flags.base : undefined
|
|
358
359
|
const branchFlag = typeof ctx.args.flags.branch === 'string' ? ctx.args.flags.branch : undefined
|
|
359
360
|
const result = await createCliTab(ctx, {
|
|
@@ -364,9 +365,9 @@ export const tabCreate: CliCommand = {
|
|
|
364
365
|
cwd: cwdRaw,
|
|
365
366
|
effort,
|
|
366
367
|
model,
|
|
367
|
-
|
|
368
|
+
newWorkspace: newWorkspaceFlag,
|
|
368
369
|
title,
|
|
369
|
-
|
|
370
|
+
workspaceId: workspaceFlag,
|
|
370
371
|
})
|
|
371
372
|
writeJson(result)
|
|
372
373
|
return EXIT_OK
|
|
@@ -14,7 +14,7 @@ export const tabFocus: CliCommand = {
|
|
|
14
14
|
throw new Error('tabId is required')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const project = ctx.getProject()
|
|
18
18
|
const daemon = await ctx.getDaemon()
|
|
19
19
|
|
|
20
20
|
if (!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH)) {
|
|
@@ -22,12 +22,12 @@ export const tabFocus: CliCommand = {
|
|
|
22
22
|
'daemon predates thinAttach capability — restart aimux to pick up the new daemon'
|
|
23
23
|
)
|
|
24
24
|
}
|
|
25
|
-
await daemon.attach({ cols: 0,
|
|
25
|
+
await daemon.attach({ cols: 0, projectId: project.id, rows: 0, thin: true })
|
|
26
26
|
await daemon.expectOk('setActiveTab', { tabId })
|
|
27
27
|
|
|
28
28
|
writeJson({ ok: true })
|
|
29
29
|
return EXIT_OK
|
|
30
30
|
},
|
|
31
|
-
summary: 'Set the active tab in the
|
|
31
|
+
summary: 'Set the active tab in the project',
|
|
32
32
|
verb: 'focus',
|
|
33
33
|
}
|
|
@@ -32,7 +32,7 @@ export const tabList: CliCommand = {
|
|
|
32
32
|
],
|
|
33
33
|
group: 'tab',
|
|
34
34
|
run: async (ctx) => {
|
|
35
|
-
const
|
|
35
|
+
const project = ctx.getProject()
|
|
36
36
|
const daemon = await ctx.getDaemon()
|
|
37
37
|
const verbose = ctx.args.flags.verbose === true
|
|
38
38
|
|
|
@@ -43,7 +43,7 @@ export const tabList: CliCommand = {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
if (daemon.hasCapability(IPC_CAPABILITY_LIST_TABS)) {
|
|
46
|
-
const result = await daemon.listTabs(
|
|
46
|
+
const result = await daemon.listTabs(project.id)
|
|
47
47
|
const tabs = verbose ? result.tabs : result.tabs.map(stripLastLine)
|
|
48
48
|
writeJson({ activeTabId: result.activeTabId, tabs })
|
|
49
49
|
return EXIT_OK
|
|
@@ -56,12 +56,12 @@ export const tabList: CliCommand = {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// Fallback: thin-attach to read the same information without resizing the
|
|
59
|
-
//
|
|
59
|
+
// project. Pre-listTabs daemons that advertise thinAttach would in
|
|
60
60
|
// principle land here, but that combination shouldn't ship.
|
|
61
61
|
const attach = await daemon.attach({
|
|
62
62
|
cols: 0,
|
|
63
|
+
projectId: project.id,
|
|
63
64
|
rows: 0,
|
|
64
|
-
sessionId: workspace.id,
|
|
65
65
|
thin: true,
|
|
66
66
|
})
|
|
67
67
|
writeJson({
|
|
@@ -73,11 +73,11 @@ export const tabList: CliCommand = {
|
|
|
73
73
|
id: tab.id,
|
|
74
74
|
status: tab.status,
|
|
75
75
|
title: tab.title,
|
|
76
|
-
|
|
76
|
+
workspaceId: tab.workspaceId,
|
|
77
77
|
})),
|
|
78
78
|
})
|
|
79
79
|
return EXIT_OK
|
|
80
80
|
},
|
|
81
|
-
summary: 'List tabs in the active
|
|
81
|
+
summary: 'List tabs in the active project',
|
|
82
82
|
verb: 'list',
|
|
83
83
|
}
|
|
@@ -60,7 +60,7 @@ export const tabRun: CliCommand = {
|
|
|
60
60
|
typeof ctx.args.flags.timeout === 'number' ? ctx.args.flags.timeout : DEFAULT_TIMEOUT_MS
|
|
61
61
|
const appendEnter = ctx.args.flags['no-enter'] !== true
|
|
62
62
|
|
|
63
|
-
const
|
|
63
|
+
const project = ctx.getProject()
|
|
64
64
|
const daemon = await ctx.getDaemon()
|
|
65
65
|
if (
|
|
66
66
|
!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH) ||
|
|
@@ -72,7 +72,7 @@ export const tabRun: CliCommand = {
|
|
|
72
72
|
)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
const attach = await daemon.attach({ cols: 0,
|
|
75
|
+
const attach = await daemon.attach({ cols: 0, projectId: project.id, rows: 0, thin: true })
|
|
76
76
|
if (!attach.tabs.some((t) => t.id === tabId)) {
|
|
77
77
|
throw new Error(`tab not found: ${tabId}`)
|
|
78
78
|
}
|
|
@@ -97,7 +97,7 @@ export const tabSend: CliCommand = {
|
|
|
97
97
|
}
|
|
98
98
|
const payload = buildPromptPayload(text, asKeys)
|
|
99
99
|
|
|
100
|
-
const
|
|
100
|
+
const project = ctx.getProject()
|
|
101
101
|
const daemon = await ctx.getDaemon()
|
|
102
102
|
if (!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH)) {
|
|
103
103
|
throw new Error(
|
|
@@ -105,7 +105,7 @@ export const tabSend: CliCommand = {
|
|
|
105
105
|
)
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
await daemon.attach({ cols: 0,
|
|
108
|
+
await daemon.attach({ cols: 0, projectId: project.id, rows: 0, thin: true })
|
|
109
109
|
|
|
110
110
|
if (!awaitSubmit) {
|
|
111
111
|
const bytesWritten = await writePromptPayload(daemon, tabId, payload, appendEnter)
|
|
@@ -38,7 +38,7 @@ export const tabSnapshot: CliCommand = {
|
|
|
38
38
|
}
|
|
39
39
|
const renderOptions = { trim: ctx.args.flags['no-trim'] !== true }
|
|
40
40
|
|
|
41
|
-
const
|
|
41
|
+
const project = ctx.getProject()
|
|
42
42
|
const daemon = await ctx.getDaemon()
|
|
43
43
|
if (!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH)) {
|
|
44
44
|
throw new Error(
|
|
@@ -71,8 +71,8 @@ export const tabSnapshot: CliCommand = {
|
|
|
71
71
|
|
|
72
72
|
const attach = await daemon.attach({
|
|
73
73
|
cols: 0,
|
|
74
|
+
projectId: project.id,
|
|
74
75
|
rows: 0,
|
|
75
|
-
sessionId: workspace.id,
|
|
76
76
|
thin: true,
|
|
77
77
|
})
|
|
78
78
|
const tab = attach.tabs.find((t) => t.id === tabId)
|
|
@@ -57,7 +57,7 @@ export const tabTail: CliCommand = {
|
|
|
57
57
|
const followStatus = ctx.args.flags['follow-status'] === true
|
|
58
58
|
const timeoutMs = typeof ctx.args.flags.timeout === 'number' ? ctx.args.flags.timeout : 0
|
|
59
59
|
|
|
60
|
-
const
|
|
60
|
+
const project = ctx.getProject()
|
|
61
61
|
const daemon = await ctx.getDaemon()
|
|
62
62
|
if (!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH)) {
|
|
63
63
|
throw new Error(
|
|
@@ -69,7 +69,7 @@ export const tabTail: CliCommand = {
|
|
|
69
69
|
// Attach before wiring subscribers so replay renders arrive after we
|
|
70
70
|
// print the "attached" marker; that keeps NDJSON output deterministic
|
|
71
71
|
// for downstream consumers.
|
|
72
|
-
const attach = await daemon.attach({ cols: 0,
|
|
72
|
+
const attach = await daemon.attach({ cols: 0, projectId: project.id, rows: 0, thin: true })
|
|
73
73
|
|
|
74
74
|
// Fail fast on a bad tabId — otherwise tail would sit silent until
|
|
75
75
|
// --timeout, since no matching tabRender/tabExit would ever fire.
|
|
@@ -36,7 +36,7 @@ export const tabWait: CliCommand = {
|
|
|
36
36
|
const timeoutMs =
|
|
37
37
|
typeof ctx.args.flags.timeout === 'number' ? ctx.args.flags.timeout : DEFAULT_TIMEOUT_MS
|
|
38
38
|
|
|
39
|
-
const
|
|
39
|
+
const project = ctx.getProject()
|
|
40
40
|
const daemon = await ctx.getDaemon()
|
|
41
41
|
if (!daemon.hasCapability(IPC_CAPABILITY_THIN_ATTACH)) {
|
|
42
42
|
throw new Error(
|
|
@@ -46,8 +46,8 @@ export const tabWait: CliCommand = {
|
|
|
46
46
|
|
|
47
47
|
const attach = await daemon.attach({
|
|
48
48
|
cols: 0,
|
|
49
|
+
projectId: project.id,
|
|
49
50
|
rows: 0,
|
|
50
|
-
sessionId: workspace.id,
|
|
51
51
|
thin: true,
|
|
52
52
|
})
|
|
53
53
|
|
|
@@ -19,14 +19,14 @@ export const workerAwait: CliCommand = {
|
|
|
19
19
|
],
|
|
20
20
|
group: 'worker',
|
|
21
21
|
run: async (ctx) => {
|
|
22
|
-
const {
|
|
22
|
+
const { project, tab } = await resolveWorkerTarget(ctx, ctx.args.positionals[0] ?? '')
|
|
23
23
|
const outcome = await awaitExistingWorker(
|
|
24
24
|
ctx,
|
|
25
|
-
|
|
25
|
+
project,
|
|
26
26
|
tab.id,
|
|
27
27
|
typeof ctx.args.flags.timeout === 'number' ? ctx.args.flags.timeout : DEFAULT_TIMEOUT_MS
|
|
28
28
|
)
|
|
29
|
-
writeJson(workerEnvelope(
|
|
29
|
+
writeJson(workerEnvelope(project, workerView(project, tab), outcome))
|
|
30
30
|
return workerOutcomeExitCode(outcome)
|
|
31
31
|
},
|
|
32
32
|
summary: "Await an existing worker's in-flight turn",
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
IPC_CAPABILITY_THIN_ATTACH,
|
|
12
12
|
IPC_CAPABILITY_TURN_LIFECYCLE,
|
|
13
13
|
IPC_CAPABILITY_WORKER_METADATA,
|
|
14
|
-
|
|
14
|
+
IPC_CAPABILITY_WORKSPACE_LIFECYCLE_EVENTS,
|
|
15
15
|
} from '../../../ipc/protocol'
|
|
16
16
|
import {
|
|
17
17
|
getAllAssistantOptions,
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
parseCommand,
|
|
20
20
|
} from '../../../pty/command-registry'
|
|
21
21
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} from '../../client/
|
|
22
|
+
findPrimaryWorkspace,
|
|
23
|
+
PROJECT_ENV_VAR,
|
|
24
|
+
projectRepoRoot,
|
|
25
|
+
} from '../../client/project-resolver'
|
|
26
26
|
import { SHARED_FLAGS } from '../../flags'
|
|
27
27
|
import { EXIT_OK, EXIT_RUNTIME, writeJson } from '../../output'
|
|
28
28
|
import { WORKER_SCHEMA_VERSION } from './shared'
|
|
@@ -33,7 +33,7 @@ const REQUIRED_DAEMON_CAPABILITIES = [
|
|
|
33
33
|
IPC_CAPABILITY_THIN_ATTACH,
|
|
34
34
|
IPC_CAPABILITY_TURN_LIFECYCLE,
|
|
35
35
|
IPC_CAPABILITY_WORKER_METADATA,
|
|
36
|
-
|
|
36
|
+
IPC_CAPABILITY_WORKSPACE_LIFECYCLE_EVENTS,
|
|
37
37
|
] as const
|
|
38
38
|
|
|
39
39
|
export const workerDoctor: CliCommand = {
|
|
@@ -42,7 +42,7 @@ export const workerDoctor: CliCommand = {
|
|
|
42
42
|
group: 'worker',
|
|
43
43
|
run: async (ctx) => {
|
|
44
44
|
const daemon = await ctx.getDaemon()
|
|
45
|
-
const
|
|
45
|
+
const project = ctx.getProject()
|
|
46
46
|
const { version } = await import('../../../../package.json')
|
|
47
47
|
const { customCommands } = loadConfig()
|
|
48
48
|
const assistants = getAllAssistantOptions(customCommands).map((assistant) => ({
|
|
@@ -61,8 +61,8 @@ export const workerDoctor: CliCommand = {
|
|
|
61
61
|
const missingManagerCapabilities = [MANAGER_CAPABILITY_WORKER_METADATA].filter(
|
|
62
62
|
(capability) => !managerCapabilities.includes(capability)
|
|
63
63
|
)
|
|
64
|
-
const
|
|
65
|
-
const
|
|
64
|
+
const primaryWorkspace = findPrimaryWorkspace(project)
|
|
65
|
+
const projectOrigin = ctx.getProjectOrigin?.() ?? 'active'
|
|
66
66
|
const availableAssistants = assistants.filter((assistant) => assistant.available)
|
|
67
67
|
const skillPath = fileURLToPath(
|
|
68
68
|
new URL('../../../../skills/aimux-orchestrator/', import.meta.url)
|
|
@@ -78,8 +78,8 @@ export const workerDoctor: CliCommand = {
|
|
|
78
78
|
`restart the terminal manager; it is missing: ${missingManagerCapabilities.join(', ')}`
|
|
79
79
|
)
|
|
80
80
|
}
|
|
81
|
-
if (
|
|
82
|
-
issues.push('
|
|
81
|
+
if (primaryWorkspace === undefined) {
|
|
82
|
+
issues.push('project has no primary workspace; default isolated worker runs are unavailable')
|
|
83
83
|
}
|
|
84
84
|
if (availableAssistants.length === 0) {
|
|
85
85
|
issues.push('no configured assistant executable is available on PATH')
|
|
@@ -87,14 +87,14 @@ export const workerDoctor: CliCommand = {
|
|
|
87
87
|
if (!existsSync(skillPath)) {
|
|
88
88
|
issues.push(`packaged orchestrator skill is missing: ${skillPath}`)
|
|
89
89
|
}
|
|
90
|
-
// Not an issue — an inferred
|
|
90
|
+
// Not an issue — an inferred project is the normal interactive case — but
|
|
91
91
|
// it IS the one resolution mode that can follow the UI to another project
|
|
92
92
|
// between two calls. An orchestrator dispatching a multi-hour fleet wants to
|
|
93
93
|
// see this before it starts, not after it reviews diffs from the wrong repo.
|
|
94
94
|
const warnings: string[] = []
|
|
95
|
-
if (
|
|
95
|
+
if (projectOrigin === 'active') {
|
|
96
96
|
warnings.push(
|
|
97
|
-
`
|
|
97
|
+
`project "${project.name}" was inferred from the most recently opened project and follows the UI; pin it with --project or ${PROJECT_ENV_VAR}`
|
|
98
98
|
)
|
|
99
99
|
}
|
|
100
100
|
const ready = issues.length === 0
|
|
@@ -113,16 +113,16 @@ export const workerDoctor: CliCommand = {
|
|
|
113
113
|
missing: missingManagerCapabilities,
|
|
114
114
|
ok: missingManagerCapabilities.length === 0,
|
|
115
115
|
},
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
repoRoot: workspaceRepoRoot(workspace),
|
|
116
|
+
project: {
|
|
117
|
+
hasPrimaryWorkspace: primaryWorkspace !== undefined,
|
|
118
|
+
name: project.name,
|
|
119
|
+
ok: primaryWorkspace !== undefined,
|
|
120
|
+
/** Repo every fresh worker workspace is cut from — confirm before dispatching. */
|
|
121
|
+
repoRoot: projectRepoRoot(project),
|
|
123
122
|
/** 'flag' | 'env' | 'active'; only 'active' can follow the UI. */
|
|
124
|
-
source:
|
|
123
|
+
source: projectOrigin,
|
|
125
124
|
},
|
|
125
|
+
skill: { ok: existsSync(skillPath), path: skillPath },
|
|
126
126
|
},
|
|
127
127
|
cliVersion: version,
|
|
128
128
|
daemon: {
|
|
@@ -134,20 +134,20 @@ export const workerDoctor: CliCommand = {
|
|
|
134
134
|
protocolVersion: daemon.getSelectedVersion(),
|
|
135
135
|
},
|
|
136
136
|
issues,
|
|
137
|
+
project: {
|
|
138
|
+
id: project.id,
|
|
139
|
+
name: project.name,
|
|
140
|
+
projectPath: project.projectPath ?? null,
|
|
141
|
+
repoRoot: projectRepoRoot(project),
|
|
142
|
+
source: projectOrigin,
|
|
143
|
+
},
|
|
137
144
|
ready,
|
|
138
145
|
schemaVersion: WORKER_SCHEMA_VERSION,
|
|
139
146
|
skillPath,
|
|
140
147
|
warnings,
|
|
141
|
-
workspace: {
|
|
142
|
-
id: workspace.id,
|
|
143
|
-
name: workspace.name,
|
|
144
|
-
projectPath: workspace.projectPath ?? null,
|
|
145
|
-
repoRoot: workspaceRepoRoot(workspace),
|
|
146
|
-
source: workspaceOrigin,
|
|
147
|
-
},
|
|
148
148
|
})
|
|
149
149
|
return ready ? EXIT_OK : EXIT_RUNTIME
|
|
150
150
|
},
|
|
151
|
-
summary: 'Check worker prerequisites, versions, assistants, and
|
|
151
|
+
summary: 'Check worker prerequisites, versions, assistants, and project',
|
|
152
152
|
verb: 'doctor',
|
|
153
153
|
}
|