@brimveyn/aimux 1.20.1 → 1.20.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 +9 -1
- package/package.json +1 -1
- package/skills/aimux-orchestrator/SKILL.md +39 -5
- package/skills/aimux-orchestrator/references/prompts.md +11 -0
- package/src/cli/client/workspace-resolver.ts +61 -8
- package/src/cli/commands/tab/await.ts +1 -1
- package/src/cli/commands/tab/close.ts +1 -1
- package/src/cli/commands/tab/create.ts +27 -3
- package/src/cli/commands/tab/focus.ts +1 -1
- package/src/cli/commands/tab/prompt-io.ts +6 -1
- package/src/cli/commands/tab/run.ts +10 -2
- package/src/cli/commands/tab/send.ts +12 -7
- package/src/cli/commands/tab/snapshot.ts +2 -1
- package/src/cli/commands/tab/tail.ts +1 -1
- package/src/cli/commands/tab/wait.ts +2 -1
- package/src/cli/commands/worker/await.ts +5 -4
- package/src/cli/commands/worker/doctor.ts +25 -1
- package/src/cli/commands/worker/list.ts +50 -8
- package/src/cli/commands/worker/prompt.ts +31 -6
- package/src/cli/commands/worker/run.ts +56 -10
- package/src/cli/commands/worker/shared.ts +312 -52
- package/src/cli/commands/worker/stop.ts +39 -10
- package/src/cli/commands/worker/submit.ts +40 -0
- package/src/cli/commands/workspace/close.ts +1 -1
- package/src/cli/commands/workspace/create.ts +2 -1
- package/src/cli/commands/workspace/switch.ts +1 -1
- package/src/cli/commands/worktree/create-core.ts +27 -7
- package/src/cli/commands/worktree/create.ts +18 -3
- package/src/cli/commands/worktree/remove.ts +3 -1
- package/src/cli/completion/entry.ts +181 -0
- package/src/cli/completion/install.ts +222 -0
- package/src/cli/completion/plan.ts +216 -0
- package/src/cli/completion/scripts.ts +147 -0
- package/src/cli/completion/sources.ts +74 -0
- package/src/cli/context.ts +15 -0
- package/src/cli/flags.ts +45 -2
- package/src/cli/index.ts +20 -10
- package/src/cli/output.ts +3 -0
- package/src/cli/registry.ts +2 -0
- package/src/doctor.ts +4 -0
- package/src/git/worktree.ts +15 -1
- package/src/index.tsx +35 -11
- package/src/platform/worktree-paths.ts +21 -1
package/src/index.tsx
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { runDoctor } from './doctor'
|
|
6
|
-
import { runRestartDaemon } from './restart-daemon'
|
|
7
|
-
import { runRestartTerminalManager } from './restart-terminal-manager'
|
|
8
|
-
import { createSessionBackend } from './session-backend/bootstrap'
|
|
9
|
-
import { runTerminalManager } from './terminal-manager/terminal-manager'
|
|
10
|
-
import { runUpdate } from './update'
|
|
11
|
-
|
|
2
|
+
// Every branch below imports dynamically ON PURPOSE. Static imports here would
|
|
3
|
+
// be paid by every invocation — including `aimux __complete`, which runs on
|
|
4
|
+
// each TAB press and must stay well under a keystroke's worth of latency.
|
|
12
5
|
const command = process.argv[2]
|
|
13
|
-
|
|
6
|
+
|
|
7
|
+
// Shell completion. First branch and cheapest: it loads the CLI registry and
|
|
8
|
+
// nothing else — no daemon client, no session backend, no renderer.
|
|
9
|
+
if (command === '__complete') {
|
|
10
|
+
const { runComplete } = await import('./cli/completion/entry')
|
|
11
|
+
process.exit(await runComplete(process.argv.slice(3)))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (command === 'completion') {
|
|
15
|
+
const { runCompletion } = await import('./cli/completion/entry')
|
|
16
|
+
process.exit(runCompletion(process.argv.slice(3)))
|
|
17
|
+
}
|
|
14
18
|
|
|
15
19
|
// CLI control plane (docs/reference/cli.md). Branch BEFORE the UI bootstrap so
|
|
16
20
|
// `aimux tab list` from a non-TTY shell never spins up the React renderer.
|
|
@@ -28,28 +32,38 @@ if (command === '--version' || command === '-v' || command === 'version') {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
if (command === 'doctor' || command === '--doctor') {
|
|
35
|
+
const { runDoctor } = await import('./doctor')
|
|
31
36
|
process.exit(runDoctor())
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
if (command === 'restart-daemon') {
|
|
40
|
+
const { runRestartDaemon } = await import('./restart-daemon')
|
|
35
41
|
process.exit(await runRestartDaemon())
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
if (command === 'restart-terminal-manager') {
|
|
45
|
+
const { runRestartTerminalManager } = await import('./restart-terminal-manager')
|
|
39
46
|
process.exit(await runRestartTerminalManager())
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
if (command === 'update') {
|
|
50
|
+
const { runUpdate } = await import('./update')
|
|
43
51
|
process.exit(await runUpdate())
|
|
44
52
|
}
|
|
45
53
|
|
|
54
|
+
const { logDebug } = await import('./debug/input-log')
|
|
55
|
+
const { getRuntimeProfile } = await import('./daemon/runtime-paths')
|
|
56
|
+
const runtimeProfile = getRuntimeProfile()
|
|
57
|
+
|
|
46
58
|
if (command === 'daemon') {
|
|
47
59
|
logDebug('index.daemonMode', { runtimeProfile })
|
|
60
|
+
const { runDaemon } = await import('./daemon/daemon')
|
|
48
61
|
await runDaemon()
|
|
49
62
|
}
|
|
50
63
|
|
|
51
64
|
if (command === 'terminal-manager') {
|
|
52
65
|
logDebug('index.terminalManagerMode', { runtimeProfile })
|
|
66
|
+
const { runTerminalManager } = await import('./terminal-manager/terminal-manager')
|
|
53
67
|
await runTerminalManager()
|
|
54
68
|
}
|
|
55
69
|
|
|
@@ -65,6 +79,8 @@ const [
|
|
|
65
79
|
{ loadUserConfig },
|
|
66
80
|
{ BreakingUpdateScreen },
|
|
67
81
|
{ setHostPalette },
|
|
82
|
+
{ createSessionBackend },
|
|
83
|
+
{ maybeAutoInstallCompletion },
|
|
68
84
|
] = await Promise.all([
|
|
69
85
|
import('@opentui/core'),
|
|
70
86
|
import('@opentui/react'),
|
|
@@ -72,9 +88,17 @@ const [
|
|
|
72
88
|
import('./config/loader'),
|
|
73
89
|
import('./ui/breaking-update-screen'),
|
|
74
90
|
import('./ui/host-palette'),
|
|
91
|
+
import('./session-backend/bootstrap'),
|
|
92
|
+
import('./cli/completion/install'),
|
|
75
93
|
])
|
|
76
94
|
const resolvedConfig = await loadUserConfig()
|
|
77
95
|
|
|
96
|
+
// First launch (and after every upgrade): drop the shell completion script in
|
|
97
|
+
// the conventional location for $SHELL. Silent and best-effort — it writes one
|
|
98
|
+
// file, never a dotfile, and never blocks the TUI. Opt out with
|
|
99
|
+
// AIMUX_NO_COMPLETION_INSTALL=1; `aimux doctor` reports what landed where.
|
|
100
|
+
maybeAutoInstallCompletion()
|
|
101
|
+
|
|
78
102
|
const renderer = await createCliRenderer({
|
|
79
103
|
autoFocus: true,
|
|
80
104
|
// Transparent clear color so cells untouched by BoxRenderable paints (e.g.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto'
|
|
2
|
-
import { lstat, mkdir, realpath } from 'node:fs/promises'
|
|
2
|
+
import { lstat, mkdir, realpath, rmdir } from 'node:fs/promises'
|
|
3
3
|
import { join, resolve } from 'node:path'
|
|
4
4
|
|
|
5
5
|
const DEFAULT_WORKTREE_ROOT = '/tmp/aimux-wt'
|
|
@@ -55,6 +55,26 @@ export async function ensureAimuxWorktreeRoot(): Promise<string> {
|
|
|
55
55
|
return root
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Drop the repo-scoped `<root>/r-<hash>` parent of a removed worktree when it is
|
|
60
|
+
* empty. `assertSafeAimuxWorktreePath` creates that directory before git runs,
|
|
61
|
+
* so a failed or rolled-back creation used to leave one behind forever. Silent
|
|
62
|
+
* on ENOTEMPTY (another worktree for the same repo is still live) and on any
|
|
63
|
+
* other error — this is housekeeping, never the point of the operation.
|
|
64
|
+
*/
|
|
65
|
+
export async function pruneEmptyWorktreeParent(worktreePath: string): Promise<void> {
|
|
66
|
+
if (!isInsideAimuxWorktreeRoot(worktreePath)) return
|
|
67
|
+
const parent = resolve(worktreePath, '..')
|
|
68
|
+
// Never touch the root itself — only the per-repo directory below it.
|
|
69
|
+
if (parent === resolve(getAimuxWorktreeRoot())) return
|
|
70
|
+
if (!isInsideAimuxWorktreeRoot(parent)) return
|
|
71
|
+
try {
|
|
72
|
+
await rmdir(parent)
|
|
73
|
+
} catch {
|
|
74
|
+
// Non-empty (a sibling worktree is live) or already gone. Either is fine.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
58
78
|
export async function assertSafeAimuxWorktreePath(path: string): Promise<void> {
|
|
59
79
|
const root = await ensureAimuxWorktreeRoot()
|
|
60
80
|
if (!isInsideAimuxWorktreeRoot(path)) {
|