borgmcp 3.4.0 → 3.5.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 +20 -2
- package/dist/backends/{launch-all-windows.d.ts → launch-all-terminals.d.ts} +5 -3
- package/dist/backends/launch-all-terminals.d.ts.map +1 -0
- package/dist/backends/{launch-all-windows.js → launch-all-terminals.js} +26 -12
- package/dist/backends/launch-all-terminals.js.map +1 -0
- package/dist/bare-launch-menu.d.ts +53 -16
- package/dist/bare-launch-menu.d.ts.map +1 -1
- package/dist/bare-launch-menu.js +95 -4
- package/dist/bare-launch-menu.js.map +1 -1
- package/dist/claude.d.ts +6 -0
- package/dist/claude.d.ts.map +1 -1
- package/dist/claude.js +83 -8
- package/dist/claude.js.map +1 -1
- package/dist/cli-help.d.ts +2 -0
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +31 -2
- package/dist/cli-help.js.map +1 -1
- package/dist/config-utils.d.ts +12 -6
- package/dist/config-utils.d.ts.map +1 -1
- package/dist/config-utils.js +30 -7
- package/dist/config-utils.js.map +1 -1
- package/dist/cubes.d.ts +17 -0
- package/dist/cubes.d.ts.map +1 -1
- package/dist/cubes.js +87 -1
- package/dist/cubes.js.map +1 -1
- package/dist/ensure-mcp-config.d.ts.map +1 -1
- package/dist/ensure-mcp-config.js +5 -2
- package/dist/ensure-mcp-config.js.map +1 -1
- package/dist/launch-all-cmd.d.ts.map +1 -1
- package/dist/launch-all-cmd.js +20 -10
- package/dist/launch-all-cmd.js.map +1 -1
- package/dist/parse-launch-all-args.d.ts +1 -1
- package/dist/parse-launch-all-args.d.ts.map +1 -1
- package/dist/parse-launch-all-args.js +3 -3
- package/dist/parse-launch-all-args.js.map +1 -1
- package/dist/seat-commands.d.ts +58 -0
- package/dist/seat-commands.d.ts.map +1 -0
- package/dist/seat-commands.js +240 -0
- package/dist/seat-commands.js.map +1 -0
- package/dist/seats.d.ts +8 -0
- package/dist/seats.d.ts.map +1 -1
- package/dist/seats.js +14 -0
- package/dist/seats.js.map +1 -1
- package/dist/unknown-subcommand.d.ts +1 -1
- package/dist/unknown-subcommand.d.ts.map +1 -1
- package/dist/unknown-subcommand.js +2 -0
- package/dist/unknown-subcommand.js.map +1 -1
- package/package.json +1 -1
- package/src/backends/{launch-all-windows.ts → launch-all-terminals.ts} +33 -15
- package/src/bare-launch-menu.ts +141 -18
- package/src/claude.ts +127 -7
- package/src/cli-help.ts +37 -2
- package/src/config-utils.ts +32 -7
- package/src/cubes.ts +118 -1
- package/src/ensure-mcp-config.ts +5 -2
- package/src/launch-all-cmd.ts +24 -11
- package/src/parse-launch-all-args.ts +4 -4
- package/src/seat-commands.ts +322 -0
- package/src/seats.ts +15 -0
- package/src/unknown-subcommand.ts +2 -0
- package/dist/backends/launch-all-windows.d.ts.map +0 -1
- package/dist/backends/launch-all-windows.js.map +0 -1
package/README.md
CHANGED
|
@@ -84,8 +84,26 @@ continue:
|
|
|
84
84
|
The lookup is the same for Claude Code, Codex, and OpenCode; only their launch
|
|
85
85
|
adapters differ. It is also the same for an in-place drone and a sibling drone
|
|
86
86
|
worktree: run `borg` inside the worktree where the drone was assimilated.
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
In a TTY, running `borg` in the repository's main worktree offers the repository's drones so you can pick one to resume.
|
|
88
|
+
|
|
89
|
+
You do not have to remember worktree paths. To list the drones registered on
|
|
90
|
+
this machine, run:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
borg seats
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
To resume one drone from any directory, run:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
borg launch <label-or-id-prefix>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`borg launch` finds the drone's worktree in the local seat registry and starts
|
|
103
|
+
it exactly as if you ran `borg` in that worktree. If a label exists in more
|
|
104
|
+
than one cube, add `--cube <name>` or use the drone id prefix.
|
|
105
|
+
|
|
106
|
+
To resume all saved drone worktrees for a cube, run:
|
|
89
107
|
|
|
90
108
|
```bash
|
|
91
109
|
borg launch-all [cube]
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { DroneCandidate } from '../launch-all-discovery.js';
|
|
2
2
|
import type { LaunchAllDeps } from '../launch-all-deps.js';
|
|
3
|
-
export interface
|
|
3
|
+
export interface TerminalsOpts {
|
|
4
4
|
borgPath: string;
|
|
5
5
|
platform: NodeJS.Platform;
|
|
6
|
+
cubeName: string;
|
|
6
7
|
launchedAtISO: string;
|
|
7
8
|
/** Stagger between drone launches (ms) to avoid the rate limiter; 0 disables. */
|
|
8
9
|
launchDelayMs: number;
|
|
9
10
|
/** Injectable sleep (real setTimeout in prod; no-op spy in tests). */
|
|
10
11
|
sleep: (ms: number) => Promise<void>;
|
|
11
12
|
}
|
|
12
|
-
export declare function
|
|
13
|
-
|
|
13
|
+
export declare function hasMacOSTerminalApp(deps: Pick<LaunchAllDeps, 'pathExists'>): boolean;
|
|
14
|
+
export declare function runTerminalsBackend(candidates: DroneCandidate[], opts: TerminalsOpts, deps: LaunchAllDeps): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=launch-all-terminals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-terminals.d.ts","sourceRoot":"","sources":["../../src/backends/launch-all-terminals.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAa3D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AASD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,GAAG,OAAO,CAEpF;AAoED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,cAAc,EAAE,EAC5B,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
//
|
|
1
|
+
// client#400 — terminals backend (`--mode terminals`; macOS auto default).
|
|
2
2
|
// Opens each worktree as a new terminal window/tab. macOS: iTerm/Terminal via
|
|
3
3
|
// osascript. Linux: $BORG_TERMINAL / $TERMINAL / probed emulator. No shared
|
|
4
4
|
// session, so no post-launch attach. Hard-fails if no compatible terminal found.
|
|
5
5
|
import { buildLaunchCommand } from '../launch-all-command.js';
|
|
6
6
|
import { writeLockMarker } from '../launch-all-locks.js';
|
|
7
|
+
import { composeTerminalTitle } from '../terminal-title.js';
|
|
8
|
+
import { shellEscape } from '../shell-escape.js';
|
|
9
|
+
const ITERM_APP = '/Applications/iTerm.app';
|
|
10
|
+
const TERMINAL_APPS = [
|
|
11
|
+
'/System/Applications/Utilities/Terminal.app',
|
|
12
|
+
'/Applications/Utilities/Terminal.app',
|
|
13
|
+
'/Applications/Terminal.app',
|
|
14
|
+
];
|
|
7
15
|
/** AppleScript string-literal escaping (backslash + double-quote). */
|
|
8
16
|
function appleScriptEscape(s) {
|
|
9
17
|
return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
10
18
|
}
|
|
11
19
|
class NoTerminalError extends Error {
|
|
12
20
|
}
|
|
21
|
+
export function hasMacOSTerminalApp(deps) {
|
|
22
|
+
return deps.pathExists(ITERM_APP) || TERMINAL_APPS.some((path) => deps.pathExists(path));
|
|
23
|
+
}
|
|
13
24
|
/** macOS: open each candidate in iTerm or Terminal via osascript. */
|
|
14
25
|
async function launchMacOS(candidates, opts, deps) {
|
|
15
|
-
const hasITerm = deps.pathExists(
|
|
16
|
-
const hasTerminal = deps.pathExists(
|
|
26
|
+
const hasITerm = deps.pathExists(ITERM_APP);
|
|
27
|
+
const hasTerminal = TERMINAL_APPS.some((path) => deps.pathExists(path));
|
|
17
28
|
if (!hasITerm && !hasTerminal) {
|
|
18
|
-
throw new NoTerminalError('borg launch-all: --mode
|
|
29
|
+
throw new NoTerminalError('borg launch-all: --mode terminals requires a compatible terminal app.\n' +
|
|
19
30
|
'Not found: iTerm.app, Terminal.app\n' +
|
|
20
31
|
'Install iTerm2 (https://iterm2.com) or use --mode tmux (brew install tmux).\n');
|
|
21
32
|
}
|
|
@@ -24,9 +35,10 @@ async function launchMacOS(candidates, opts, deps) {
|
|
|
24
35
|
if (i > 0 && opts.launchDelayMs > 0)
|
|
25
36
|
await opts.sleep(opts.launchDelayMs); // rate-limit stagger
|
|
26
37
|
const cmd = buildLaunchCommand(c.worktreeDir, opts.borgPath);
|
|
38
|
+
const title = composeTerminalTitle({ label: c.droneLabel, cubeName: opts.cubeName }, '');
|
|
27
39
|
const script = hasITerm
|
|
28
|
-
? `tell application "iTerm"\n tell current window to create tab with default profile command "${appleScriptEscape(cmd)}"\nend tell`
|
|
29
|
-
: `tell application "Terminal"\n do script "${appleScriptEscape(cmd)}"\n activate\nend tell`;
|
|
40
|
+
? `tell application "iTerm"\n if (count of windows) = 0 then\n set launchedWindow to (create window with default profile command "${appleScriptEscape(cmd)}")\n tell current session of launchedWindow to set name to "${appleScriptEscape(title)}"\n else\n tell current window\n set launchedTab to (create tab with default profile command "${appleScriptEscape(cmd)}")\n tell current session of launchedTab to set name to "${appleScriptEscape(title)}"\n end tell\n end if\nend tell`
|
|
41
|
+
: `tell application "Terminal"\n set launchedTab to do script "${appleScriptEscape(cmd)}"\n set custom title of launchedTab to "${appleScriptEscape(title)}"\n set title displays custom title of launchedTab to true\n activate\nend tell`;
|
|
30
42
|
deps.runSync('osascript', ['-e', script]);
|
|
31
43
|
writeLockMarker(deps, c.cubeId, c.droneLabel, c.worktreeDir, opts.launchedAtISO);
|
|
32
44
|
}
|
|
@@ -45,14 +57,16 @@ async function launchLinux(candidates, opts, deps) {
|
|
|
45
57
|
}
|
|
46
58
|
}
|
|
47
59
|
if (!term) {
|
|
48
|
-
throw new NoTerminalError('borg launch-all: --mode
|
|
60
|
+
throw new NoTerminalError('borg launch-all: --mode terminals requires a terminal emulator.\n' +
|
|
49
61
|
'Not found. Set $BORG_TERMINAL=<path> or use --mode tmux.\n');
|
|
50
62
|
}
|
|
51
63
|
for (let i = 0; i < candidates.length; i++) {
|
|
52
64
|
const c = candidates[i];
|
|
53
65
|
if (i > 0 && opts.launchDelayMs > 0)
|
|
54
66
|
await opts.sleep(opts.launchDelayMs); // rate-limit stagger
|
|
55
|
-
const
|
|
67
|
+
const title = composeTerminalTitle({ label: c.droneLabel, cubeName: opts.cubeName }, '');
|
|
68
|
+
const cmd = `printf '\\033]0;%s\\007' ${shellEscape(title)}; ` +
|
|
69
|
+
buildLaunchCommand(c.worktreeDir, opts.borgPath, { keepOpenOnFail: true });
|
|
56
70
|
// `<term> -e sh -c '<cmd>'` opens a new window running the command.
|
|
57
71
|
deps.runSync(term, ['-e', 'sh', '-c', cmd]);
|
|
58
72
|
writeLockMarker(deps, c.cubeId, c.droneLabel, c.worktreeDir, opts.launchedAtISO);
|
|
@@ -64,14 +78,14 @@ async function launchLinux(candidates, opts, deps) {
|
|
|
64
78
|
* string literal (parse error). Reject such paths up front (the user's own path;
|
|
65
79
|
* pathological) — fail-loud + skip, never silently mangle. Applies to both
|
|
66
80
|
* platforms defensively (the tmux primary handles control chars fine via
|
|
67
|
-
* shellEscape + array-args, so this guard is
|
|
81
|
+
* shellEscape + array-args, so this guard is terminals-backend-specific).
|
|
68
82
|
*/
|
|
69
83
|
const CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/;
|
|
70
|
-
export async function
|
|
84
|
+
export async function runTerminalsBackend(candidates, opts, deps) {
|
|
71
85
|
const safe = candidates.filter((c) => {
|
|
72
86
|
if (CONTROL_CHAR_RE.test(c.worktreeDir)) {
|
|
73
87
|
deps.stderr(`skipping ${c.droneLabel} (${JSON.stringify(c.worktreeDir)}): worktree path contains a control ` +
|
|
74
|
-
`character — unsafe for --mode
|
|
88
|
+
`character — unsafe for --mode terminals; use --mode tmux instead.\n`);
|
|
75
89
|
return false;
|
|
76
90
|
}
|
|
77
91
|
return true;
|
|
@@ -83,4 +97,4 @@ export async function runWindowsBackend(candidates, opts, deps) {
|
|
|
83
97
|
await launchLinux(safe, opts, deps);
|
|
84
98
|
}
|
|
85
99
|
}
|
|
86
|
-
//# sourceMappingURL=launch-all-
|
|
100
|
+
//# sourceMappingURL=launch-all-terminals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-all-terminals.js","sourceRoot":"","sources":["../../src/backends/launch-all-terminals.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8EAA8E;AAC9E,4EAA4E;AAC5E,iFAAiF;AAIjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,SAAS,GAAG,yBAAyB,CAAC;AAC5C,MAAM,aAAa,GAAG;IACpB,6CAA6C;IAC7C,sCAAsC;IACtC,4BAA4B;CACpB,CAAC;AAaX,sEAAsE;AACtE,SAAS,iBAAiB,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,eAAgB,SAAQ,KAAK;CAAG;AAEtC,MAAM,UAAU,mBAAmB,CAAC,IAAuC;IACzE,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,qEAAqE;AACrE,KAAK,UAAU,WAAW,CAAC,UAA4B,EAAE,IAAmB,EAAE,IAAmB;IAC/F,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;QAC9B,MAAM,IAAI,eAAe,CACvB,yEAAyE;YACvE,sCAAsC;YACtC,+EAA+E,CAClF,CAAC;IACJ,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,qBAAqB;QAChG,MAAM,GAAG,GAAG,kBAAkB,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,oBAAoB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACzF,MAAM,MAAM,GAAG,QAAQ;YACrB,CAAC,CAAC,sIAAsI,iBAAiB,CAAC,GAAG,CAAC,kEAAkE,iBAAiB,CAAC,KAAK,CAAC,0GAA0G,iBAAiB,CAAC,GAAG,CAAC,iEAAiE,iBAAiB,CAAC,KAAK,CAAC,qCAAqC;YACtf,CAAC,CAAC,gEAAgE,iBAAiB,CAAC,GAAG,CAAC,4CAA4C,iBAAiB,CAAC,KAAK,CAAC,mFAAmF,CAAC;QAClP,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC1C,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,KAAK,UAAU,WAAW,CAAC,UAA4B,EAAE,IAAmB,EAAE,IAAmB;IAC/F,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,CAAC,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACzE,IAAI,IAAI,GAAuB,QAAQ,CAAC;IACxC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChD,IAAI,GAAG,IAAI,CAAC;gBACZ,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,eAAe,CACvB,mEAAmE;YACjE,4DAA4D,CAC/D,CAAC;IACJ,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,qBAAqB;QAChG,MAAM,KAAK,GAAG,oBAAoB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACzF,MAAM,GAAG,GACP,4BAA4B,WAAW,CAAC,KAAK,CAAC,IAAI;YAClD,kBAAkB,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,oEAAoE;QACpE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5C,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IACnF,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,eAAe,GAAG,iBAAiB,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAA4B,EAC5B,IAAmB,EACnB,IAAmB;IAEnB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACnC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,CACT,YAAY,CAAC,CAAC,UAAU,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,sCAAsC;gBAC9F,qEAAqE,CACxE,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;SAAM,CAAC;QACN,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
|
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* gh#853 — bare `borg` (no-args) interactive launch menu.
|
|
3
3
|
*
|
|
4
|
-
* When `borg` is run with NO arguments in a TTY
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 2. Launch with <other> instead — the OTHER configured agent, ONE-SHOT
|
|
8
|
-
* (does NOT persist the preference).
|
|
9
|
-
* 3. Launch all — runLaunchAll for the active cube.
|
|
4
|
+
* When `borg` is run with NO arguments in a TTY outside an active seat, offer
|
|
5
|
+
* a small launch selector. In a repository with live sibling drones, those
|
|
6
|
+
* drones come first; otherwise the existing agent choices remain unchanged.
|
|
10
7
|
*
|
|
11
8
|
* The option-set, the selection→action mapping, and the show/collapse decision
|
|
12
9
|
* are pure functions so they're unit-testable without a real TTY. claude.ts
|
|
13
|
-
* main() is thin glue: it computes the
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* main() is thin glue: it computes the available candidates and agent choices,
|
|
11
|
+
* gates on shouldShowLaunchMenu, runs the orchestrator with the real readline
|
|
12
|
+
* prompt, then dispatches the returned action.
|
|
16
13
|
*
|
|
17
|
-
* Load-bearing safety: TTY-only + bare-args-only
|
|
18
|
-
* scripted/programmatic
|
|
14
|
+
* Load-bearing safety: TTY-only + bare-args-only + no-active-seat
|
|
15
|
+
* (shouldShowLaunchMenu), so scripted/programmatic invocations and direct
|
|
16
|
+
* worktree resumes are untouched.
|
|
19
17
|
*/
|
|
20
|
-
import type { BorgCli } from './cubes.js';
|
|
18
|
+
import type { ActiveCube, BorgCli } from './cubes.js';
|
|
19
|
+
import type { DroneCandidate } from './launch-all-discovery.js';
|
|
20
|
+
import type { SeatStatus } from './seat-probe.js';
|
|
21
21
|
export type LaunchMenuAction = {
|
|
22
22
|
kind: 'launch';
|
|
23
23
|
cli: BorgCli;
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'launch-seat';
|
|
26
|
+
target: string;
|
|
24
27
|
} | {
|
|
25
28
|
kind: 'launch-all';
|
|
29
|
+
cubeId?: string;
|
|
26
30
|
};
|
|
31
|
+
export interface LaunchMenuDroneCandidate {
|
|
32
|
+
droneLabel: string;
|
|
33
|
+
target: string;
|
|
34
|
+
worktree: string;
|
|
35
|
+
}
|
|
27
36
|
export interface LaunchMenuOption {
|
|
28
37
|
/** The keystroke that selects this option (sequential: '1', '2', …). */
|
|
29
38
|
key: string;
|
|
@@ -35,9 +44,35 @@ export interface LaunchMenuInputs {
|
|
|
35
44
|
defaultCli: BorgCli;
|
|
36
45
|
/** All configured agents that are NOT the default, in display order. */
|
|
37
46
|
otherConfiguredClis: BorgCli[];
|
|
38
|
-
/** True iff
|
|
47
|
+
/** True iff the current menu context has launch-all targets. */
|
|
39
48
|
hasLaunchAllTargets: boolean;
|
|
49
|
+
/** Live sibling drones offered before the unattached launch choices. */
|
|
50
|
+
droneCandidates?: LaunchMenuDroneCandidate[];
|
|
51
|
+
/** Cube selected by the sibling-drone context for its launch-all action. */
|
|
52
|
+
launchAllCubeId?: string;
|
|
53
|
+
}
|
|
54
|
+
interface LaunchMenuCandidateDeps {
|
|
55
|
+
readAllProjectIdentities: () => Promise<Array<{
|
|
56
|
+
projectPath: string;
|
|
57
|
+
cube: ActiveCube;
|
|
58
|
+
}>>;
|
|
59
|
+
discoverDroneCandidates: (cubeId: string) => Promise<DroneCandidate[]>;
|
|
60
|
+
getActiveSeatForWorktree: (worktree: string) => Promise<{
|
|
61
|
+
cubeId: string;
|
|
62
|
+
droneId?: string;
|
|
63
|
+
} | null>;
|
|
64
|
+
pathExists: (worktree: string) => boolean;
|
|
65
|
+
probeSeat: (candidate: DroneCandidate) => Promise<SeatStatus>;
|
|
40
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Find linked sibling worktrees that still own their preferred active seat.
|
|
69
|
+
* Authoritative terminal probe results are omitted; transient/unknown probe
|
|
70
|
+
* results stay visible, matching launch-all's constructive fail-open behavior.
|
|
71
|
+
*/
|
|
72
|
+
export declare function discoverLiveLaunchMenuCandidates(deps: LaunchMenuCandidateDeps): Promise<{
|
|
73
|
+
candidates: LaunchMenuDroneCandidate[];
|
|
74
|
+
launchAllCubeId?: string;
|
|
75
|
+
}>;
|
|
41
76
|
/**
|
|
42
77
|
* Resolve and configure the CLI that will actually launch.
|
|
43
78
|
*
|
|
@@ -47,14 +82,15 @@ export interface LaunchMenuInputs {
|
|
|
47
82
|
*/
|
|
48
83
|
export declare function configureSelectedLaunchCli(defaultCli: BorgCli, action: LaunchMenuAction | undefined, configure: (cli: BorgCli) => void): BorgCli;
|
|
49
84
|
/**
|
|
50
|
-
* Gate: the menu fires ONLY for bare `borg` (no args) in a TTY
|
|
51
|
-
*
|
|
52
|
-
* through to the existing
|
|
85
|
+
* Gate: the menu fires ONLY for bare `borg` (no args) in a TTY without an
|
|
86
|
+
* active seat. Explicit invocations, non-TTY launches, and direct worktree
|
|
87
|
+
* resumes fall straight through to the existing launch path.
|
|
53
88
|
*/
|
|
54
89
|
export declare function shouldShowLaunchMenu(args: {
|
|
55
90
|
extraArgs: string[];
|
|
56
91
|
stdinIsTTY: boolean;
|
|
57
92
|
stdoutIsTTY: boolean;
|
|
93
|
+
hasActiveSeat?: boolean;
|
|
58
94
|
}): boolean;
|
|
59
95
|
export declare function explicitCliLaunchHint(args: {
|
|
60
96
|
explicitCli: BorgCli | undefined;
|
|
@@ -94,4 +130,5 @@ export declare function runBareLaunchMenu(inputs: LaunchMenuInputs, prompt: (mes
|
|
|
94
130
|
maxAttempts?: number;
|
|
95
131
|
warn?: (message: string) => void;
|
|
96
132
|
}): Promise<LaunchMenuAction>;
|
|
133
|
+
export {};
|
|
97
134
|
//# sourceMappingURL=bare-launch-menu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bare-launch-menu.d.ts","sourceRoot":"","sources":["../src/bare-launch-menu.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bare-launch-menu.d.ts","sourceRoot":"","sources":["../src/bare-launch-menu.ts"],"names":[],"mappings":"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"}
|
package/dist/bare-launch-menu.js
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
const TERMINAL_SEAT_STATUSES = new Set([
|
|
2
|
+
'evicted',
|
|
3
|
+
'revoked',
|
|
4
|
+
'rejected',
|
|
5
|
+
'credential-rejected',
|
|
6
|
+
'trust-mismatch',
|
|
7
|
+
]);
|
|
8
|
+
/**
|
|
9
|
+
* Find linked sibling worktrees that still own their preferred active seat.
|
|
10
|
+
* Authoritative terminal probe results are omitted; transient/unknown probe
|
|
11
|
+
* results stay visible, matching launch-all's constructive fail-open behavior.
|
|
12
|
+
*/
|
|
13
|
+
export async function discoverLiveLaunchMenuCandidates(deps) {
|
|
14
|
+
const identities = await deps.readAllProjectIdentities();
|
|
15
|
+
const cubeIds = [...new Set(identities.map(({ cube }) => cube.cubeId))];
|
|
16
|
+
const discovered = (await Promise.all(cubeIds.map((cubeId) => deps.discoverDroneCandidates(cubeId)))).flat();
|
|
17
|
+
const candidates = [];
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
for (const candidate of discovered) {
|
|
20
|
+
if (!deps.pathExists(candidate.worktreeDir))
|
|
21
|
+
continue;
|
|
22
|
+
const preferred = await deps.getActiveSeatForWorktree(candidate.worktreeDir);
|
|
23
|
+
if (!preferred ||
|
|
24
|
+
preferred.cubeId !== candidate.cubeId ||
|
|
25
|
+
preferred.droneId !== candidate.droneId)
|
|
26
|
+
continue;
|
|
27
|
+
let status;
|
|
28
|
+
try {
|
|
29
|
+
status = await deps.probeSeat(candidate);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
status = 'indeterminate';
|
|
33
|
+
}
|
|
34
|
+
if (TERMINAL_SEAT_STATUSES.has(status))
|
|
35
|
+
continue;
|
|
36
|
+
const key = `${candidate.cubeId}\0${candidate.droneId}\0${candidate.worktreeDir}`;
|
|
37
|
+
if (seen.has(key))
|
|
38
|
+
continue;
|
|
39
|
+
seen.add(key);
|
|
40
|
+
candidates.push({
|
|
41
|
+
cubeId: candidate.cubeId,
|
|
42
|
+
droneLabel: candidate.droneLabel,
|
|
43
|
+
target: candidate.droneId,
|
|
44
|
+
worktree: candidate.worktreeDir,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
candidates.sort((a, b) => a.droneLabel.localeCompare(b.droneLabel) || a.worktree.localeCompare(b.worktree));
|
|
48
|
+
const candidateCubeIds = new Set(candidates.map((candidate) => candidate.cubeId));
|
|
49
|
+
const launchAllCubeId = candidateCubeIds.size === 1
|
|
50
|
+
? candidates[0].cubeId
|
|
51
|
+
: undefined;
|
|
52
|
+
return {
|
|
53
|
+
candidates: candidates.map(({ cubeId: _cubeId, ...candidate }) => candidate),
|
|
54
|
+
...(launchAllCubeId ? { launchAllCubeId } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
1
57
|
/**
|
|
2
58
|
* Resolve and configure the CLI that will actually launch.
|
|
3
59
|
*
|
|
@@ -12,12 +68,15 @@ export function configureSelectedLaunchCli(defaultCli, action, configure) {
|
|
|
12
68
|
}
|
|
13
69
|
const PRETTY = { claude: 'Claude', codex: 'Codex', opencode: 'OpenCode' };
|
|
14
70
|
/**
|
|
15
|
-
* Gate: the menu fires ONLY for bare `borg` (no args) in a TTY
|
|
16
|
-
*
|
|
17
|
-
* through to the existing
|
|
71
|
+
* Gate: the menu fires ONLY for bare `borg` (no args) in a TTY without an
|
|
72
|
+
* active seat. Explicit invocations, non-TTY launches, and direct worktree
|
|
73
|
+
* resumes fall straight through to the existing launch path.
|
|
18
74
|
*/
|
|
19
75
|
export function shouldShowLaunchMenu(args) {
|
|
20
|
-
return args.extraArgs.length === 0
|
|
76
|
+
return args.extraArgs.length === 0
|
|
77
|
+
&& args.stdinIsTTY
|
|
78
|
+
&& args.stdoutIsTTY
|
|
79
|
+
&& !args.hasActiveSeat;
|
|
21
80
|
}
|
|
22
81
|
export function explicitCliLaunchHint(args) {
|
|
23
82
|
if (!args.explicitCli || !args.stdinIsTTY || !args.stdoutIsTTY)
|
|
@@ -35,6 +94,38 @@ export function shouldResolveExplicitCliLaunchHintTargets(args) {
|
|
|
35
94
|
* middle option never produces a "1) … 3) …" gap menu.
|
|
36
95
|
*/
|
|
37
96
|
export function buildLaunchMenuOptions(inputs) {
|
|
97
|
+
if (inputs.droneCandidates && inputs.droneCandidates.length > 0) {
|
|
98
|
+
const options = [...inputs.droneCandidates]
|
|
99
|
+
.sort((a, b) => a.droneLabel.localeCompare(b.droneLabel) || a.worktree.localeCompare(b.worktree))
|
|
100
|
+
.map((candidate, index) => ({
|
|
101
|
+
key: String(index + 1),
|
|
102
|
+
label: `Resume ${candidate.droneLabel} (${candidate.worktree})`,
|
|
103
|
+
action: { kind: 'launch-seat', target: candidate.target },
|
|
104
|
+
}));
|
|
105
|
+
if (inputs.hasLaunchAllTargets) {
|
|
106
|
+
options.push({
|
|
107
|
+
key: String(options.length + 1),
|
|
108
|
+
label: "Launch all (this cube's drone worktrees)",
|
|
109
|
+
action: {
|
|
110
|
+
kind: 'launch-all',
|
|
111
|
+
...(inputs.launchAllCubeId ? { cubeId: inputs.launchAllCubeId } : {}),
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
options.push({
|
|
116
|
+
key: String(options.length + 1),
|
|
117
|
+
label: `Launch ${PRETTY[inputs.defaultCli]} here without a drone`,
|
|
118
|
+
action: { kind: 'launch', cli: inputs.defaultCli },
|
|
119
|
+
});
|
|
120
|
+
for (const cli of inputs.otherConfiguredClis) {
|
|
121
|
+
options.push({
|
|
122
|
+
key: String(options.length + 1),
|
|
123
|
+
label: `Launch with ${PRETTY[cli]} here without a drone (one-shot)`,
|
|
124
|
+
action: { kind: 'launch', cli },
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return options;
|
|
128
|
+
}
|
|
38
129
|
const options = [
|
|
39
130
|
{
|
|
40
131
|
key: '1',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bare-launch-menu.js","sourceRoot":"","sources":["../src/bare-launch-menu.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bare-launch-menu.js","sourceRoot":"","sources":["../src/bare-launch-menu.ts"],"names":[],"mappings":"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"}
|
package/dist/claude.d.ts
CHANGED
|
@@ -15,9 +15,14 @@
|
|
|
15
15
|
* borg server <cmd> → Forward a lifecycle command to borg-mcp-server
|
|
16
16
|
*/
|
|
17
17
|
import { spawn } from 'child_process';
|
|
18
|
+
import { type ActiveCube, type BorgCli } from './cubes.js';
|
|
18
19
|
import { buildDefaultAssimilateDeps } from './assimilate-deps.js';
|
|
19
20
|
import { connectOpenCodeDrone, createOpenCodeLaunchKickoff } from './opencode-drone.js';
|
|
20
21
|
export type AssimilateDepsBuilder = typeof buildDefaultAssimilateDeps;
|
|
22
|
+
export declare class OpenCodeTargetedLaunchConfigError extends Error {
|
|
23
|
+
readonly code = "OPENCODE_TARGETED_LAUNCH_CONFIG";
|
|
24
|
+
constructor(droneLabel: string, worktree: string);
|
|
25
|
+
}
|
|
21
26
|
export declare function createOpenCodeLaunchPlan(cwd: string, port: number, prompt: string, passthroughArgs?: string[]): {
|
|
22
27
|
launchArgs: string[];
|
|
23
28
|
envPort: string;
|
|
@@ -40,4 +45,5 @@ export declare function launchOpenCodeProcess(options: {
|
|
|
40
45
|
process: ReturnType<typeof spawn>;
|
|
41
46
|
};
|
|
42
47
|
export declare function runAssimilateEntry(args: readonly string[], buildDeps?: AssimilateDepsBuilder): Promise<number>;
|
|
48
|
+
export declare function ensureResolvedCliConfigured(cli: BorgCli, active?: ActiveCube | null): void;
|
|
43
49
|
//# sourceMappingURL=claude.d.ts.map
|
package/dist/claude.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../src/claude.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAOtC,OAAO,EASL,KAAK,UAAU,EACf,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AAUpB,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AA0DlE,OAAO,EAAwB,oBAAoB,EAAE,2BAA2B,EAA+C,MAAM,qBAAqB,CAAC;AAM3J,MAAM,MAAM,qBAAqB,GAAG,OAAO,0BAA0B,CAAC;AAEtE,qBAAa,iCAAkC,SAAQ,KAAK;IAC1D,QAAQ,CAAC,IAAI,qCAAqC;gBAEtC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAQjD;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,eAAe,GAAE,MAAM,EAAO,GAC7B;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAO9D;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC,OAAO,2BAA2B,CAAC,CAAC;IACxD,YAAY,CAAC,EAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,oBAAoB,CAAC;CACvC,GAAG;IACF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;IAC7B,OAAO,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;CACnC,CAmBA;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,SAAS,GAAE,qBAAkD,GAC5D,OAAO,CAAC,MAAM,CAAC,CAUjB;AA+gBD,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,UAAU,GAAG,IAAW,GAAG,IAAI,CA6ChG"}
|
package/dist/claude.js
CHANGED
|
@@ -21,7 +21,7 @@ import { basename } from 'node:path';
|
|
|
21
21
|
import { createInterface } from 'node:readline/promises';
|
|
22
22
|
import { fileURLToPath } from 'node:url';
|
|
23
23
|
import chalk from 'chalk';
|
|
24
|
-
import { findProjectRoot, getActiveCube, inboxPathForDrone, setCodexWakeTarget, pruneDeadCodexWakeTargets } from './cubes.js';
|
|
24
|
+
import { BORG_LAUNCH_EXPECTED_SEAT_ENV, codexLaunchSeatExpectationConfigArgs, findProjectRoot, getActiveCube, inboxPathForDrone, LaunchSeatIdentityChangedError, setCodexWakeTarget, pruneDeadCodexWakeTargets, } from './cubes.js';
|
|
25
25
|
import { monitorStateRootForWorktree } from './inbox-monitor.js';
|
|
26
26
|
import { formatSeatReattachRefusal, inspectLiveInboxMonitor } from './seat-reattach-guard.js';
|
|
27
27
|
import { handleVersionFlag, getPackageVersion } from './version.js';
|
|
@@ -38,8 +38,9 @@ import { unknownSubcommand } from './unknown-subcommand.js';
|
|
|
38
38
|
import { parseRecoverEnrollmentArgs, runRecoverEnrollment } from './recover-enrollment-cmd.js';
|
|
39
39
|
import { runLaunchAll } from './launch-all-cmd.js';
|
|
40
40
|
import { buildDefaultLaunchAllDeps } from './launch-all-deps.js';
|
|
41
|
+
import { buildDefaultSeatCommandDeps, parseLaunchSeatArgs, parseSeatsArgs, runLaunchSeat, runSeats, } from './seat-commands.js';
|
|
41
42
|
import { discoverDroneCandidates } from './launch-all-discovery.js';
|
|
42
|
-
import { configureSelectedLaunchCli, explicitCliLaunchHint, runBareLaunchMenu, shouldResolveExplicitCliLaunchHintTargets, shouldShowLaunchMenu, } from './bare-launch-menu.js';
|
|
43
|
+
import { configureSelectedLaunchCli, discoverLiveLaunchMenuCandidates, explicitCliLaunchHint, runBareLaunchMenu, shouldResolveExplicitCliLaunchHintTargets, shouldShowLaunchMenu, } from './bare-launch-menu.js';
|
|
43
44
|
import { setTerminalTitle } from './terminal-title.js';
|
|
44
45
|
import { initConsolePrefix, consolePrefix } from './console-prefix.js';
|
|
45
46
|
import { initDebugFromArgv } from './debug.js';
|
|
@@ -58,6 +59,15 @@ import { buildOpenCodeLaunchArgs, defaultApprovalIo, resolveLaunchBorgApprovals
|
|
|
58
59
|
import { isClientOwnedCubeInitArgv, runEarlyServerFacade } from './server-facade.js';
|
|
59
60
|
import { runEarlyUpdate } from './update-cmd.js';
|
|
60
61
|
import { runDoctor, warnIfAgentIntegrationUnhealthy } from './agent-integration-health.js';
|
|
62
|
+
export class OpenCodeTargetedLaunchConfigError extends Error {
|
|
63
|
+
code = 'OPENCODE_TARGETED_LAUNCH_CONFIG';
|
|
64
|
+
constructor(droneLabel, worktree) {
|
|
65
|
+
super(`borg launch: did not launch '${droneLabel}' — borg could not update or verify the OpenCode configuration ` +
|
|
66
|
+
'that a targeted launch needs to open the correct drone. Check that the OpenCode configuration file is ' +
|
|
67
|
+
`writable, then try again. As a fallback, run \`borg\` in ${worktree} to resume that worktree's drone directly.`);
|
|
68
|
+
this.name = 'OpenCodeTargetedLaunchConfigError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
61
71
|
export function createOpenCodeLaunchPlan(cwd, port, prompt, passthroughArgs = []) {
|
|
62
72
|
const binding = openCodeLaunchBinding(port);
|
|
63
73
|
return {
|
|
@@ -197,6 +207,24 @@ async function main() {
|
|
|
197
207
|
const code = await runCleanup({}, parsed.options);
|
|
198
208
|
process.exit(code);
|
|
199
209
|
}
|
|
210
|
+
if (process.argv[2] === 'seats') {
|
|
211
|
+
const parsed = parseSeatsArgs(process.argv.slice(3));
|
|
212
|
+
if (!parsed.ok) {
|
|
213
|
+
process.stderr.write(chalk.red(`${consolePrefix()}◼ borg seats: ${parsed.error}\n`));
|
|
214
|
+
process.stderr.write(`Run \`borg seats --help\` for usage.\n`);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
process.exit(await runSeats(buildDefaultSeatCommandDeps()));
|
|
218
|
+
}
|
|
219
|
+
if (process.argv[2] === 'launch') {
|
|
220
|
+
const parsed = parseLaunchSeatArgs(process.argv.slice(3));
|
|
221
|
+
if (!parsed.ok) {
|
|
222
|
+
process.stderr.write(chalk.red(`${consolePrefix()}◼ borg launch: ${parsed.error}\n`));
|
|
223
|
+
process.stderr.write(`Run \`borg launch --help\` for usage.\n`);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
process.exit(await runLaunchSeat({ target: parsed.target, ...(parsed.cube ? { cube: parsed.cube } : {}) }, buildDefaultSeatCommandDeps()));
|
|
227
|
+
}
|
|
200
228
|
if (process.argv[2] === 'launch-all') {
|
|
201
229
|
const parsed = parseLaunchAllArgs(process.argv.slice(3));
|
|
202
230
|
if (!parsed.ok) {
|
|
@@ -274,12 +302,39 @@ async function main() {
|
|
|
274
302
|
extraArgs: process.argv.slice(2),
|
|
275
303
|
stdinIsTTY,
|
|
276
304
|
stdoutIsTTY,
|
|
305
|
+
hasActiveSeat: active !== null,
|
|
277
306
|
})) {
|
|
307
|
+
const launchAllDeps = buildDefaultLaunchAllDeps();
|
|
308
|
+
const seatCommandDeps = buildDefaultSeatCommandDeps();
|
|
309
|
+
const siblingContext = await discoverLiveLaunchMenuCandidates({
|
|
310
|
+
readAllProjectIdentities: launchAllDeps.readAllProjectIdentities,
|
|
311
|
+
discoverDroneCandidates: (cubeId) => discoverDroneCandidates({ targetCubeId: cubeId }, { ...launchAllDeps, stderr: () => { } }),
|
|
312
|
+
getActiveSeatForWorktree: seatCommandDeps.getActiveSeatForWorktree,
|
|
313
|
+
pathExists: launchAllDeps.pathExists,
|
|
314
|
+
probeSeat: (candidate) => launchAllDeps.probeSeat(candidate.sessionToken, candidate.apiUrl, candidate.serverTrustIdentity),
|
|
315
|
+
});
|
|
278
316
|
const otherConfiguredClis = configuredCliNames(detectCliAvailability(), detectCliConfiguration()).filter((c) => c !== cli);
|
|
279
|
-
const action = await runBareLaunchMenu({
|
|
317
|
+
const action = await runBareLaunchMenu({
|
|
318
|
+
defaultCli: cli,
|
|
319
|
+
otherConfiguredClis,
|
|
320
|
+
hasLaunchAllTargets: siblingContext.launchAllCubeId !== undefined,
|
|
321
|
+
droneCandidates: siblingContext.candidates,
|
|
322
|
+
...(siblingContext.launchAllCubeId
|
|
323
|
+
? { launchAllCubeId: siblingContext.launchAllCubeId }
|
|
324
|
+
: {}),
|
|
325
|
+
}, prompt);
|
|
326
|
+
if (action.kind === 'launch-seat') {
|
|
327
|
+
process.exit(await runLaunchSeat({ target: action.target }, buildDefaultSeatCommandDeps()));
|
|
328
|
+
}
|
|
280
329
|
if (action.kind === 'launch-all') {
|
|
281
|
-
const
|
|
282
|
-
const
|
|
330
|
+
const deps = buildDefaultLaunchAllDeps();
|
|
331
|
+
const selectedIdentity = action.cubeId
|
|
332
|
+
? (await deps.readAllProjectIdentities()).find(({ cube }) => cube.cubeId === action.cubeId)
|
|
333
|
+
: undefined;
|
|
334
|
+
const parsed = parseLaunchAllArgs([]);
|
|
335
|
+
const code = parsed.ok
|
|
336
|
+
? await runLaunchAll(parsed.args, selectedIdentity ? { ...deps, getActiveCube: async () => selectedIdentity.cube } : deps)
|
|
337
|
+
: 1;
|
|
283
338
|
process.exit(code);
|
|
284
339
|
}
|
|
285
340
|
// option 1 → configured default; option 2 → the other agent, ONE-SHOT
|
|
@@ -289,7 +344,7 @@ async function main() {
|
|
|
289
344
|
}
|
|
290
345
|
// Configure only the CLI that will actually launch. This must follow the
|
|
291
346
|
// one-shot menu: the resolved default can differ from the menu selection.
|
|
292
|
-
cli = configureSelectedLaunchCli(cli, launchAction, ensureResolvedCliConfigured);
|
|
347
|
+
cli = configureSelectedLaunchCli(cli, launchAction, (selectedCli) => ensureResolvedCliConfigured(selectedCli, active));
|
|
293
348
|
if (active && !parsedCli.force) {
|
|
294
349
|
const inboxPath = inboxPathForDrone(active.cubeId, active.droneId);
|
|
295
350
|
const stateRoot = monitorStateRootForWorktree(findProjectRoot(process.cwd()));
|
|
@@ -421,6 +476,7 @@ async function main() {
|
|
|
421
476
|
...codexAgentKindConfigArgs(),
|
|
422
477
|
...codexRemoteWakeConfigArgs(codexSocketPath !== null),
|
|
423
478
|
...codexStateRootConfigArgs(),
|
|
479
|
+
...codexLaunchSeatExpectationConfigArgs(),
|
|
424
480
|
...remoteArgs,
|
|
425
481
|
...withCodexCwdArg([...passthroughArgs, kickoff], process.cwd()),
|
|
426
482
|
];
|
|
@@ -503,11 +559,23 @@ async function main() {
|
|
|
503
559
|
process.exit(code ?? 0);
|
|
504
560
|
});
|
|
505
561
|
}
|
|
506
|
-
function ensureResolvedCliConfigured(cli) {
|
|
562
|
+
export function ensureResolvedCliConfigured(cli, active = null) {
|
|
507
563
|
const label = cli === 'claude' ? 'Claude Code' : cli === 'codex' ? 'Codex' : 'OpenCode';
|
|
564
|
+
const targetedOpenCodeLaunch = cli === 'opencode' &&
|
|
565
|
+
Boolean(process.env[BORG_LAUNCH_EXPECTED_SEAT_ENV]);
|
|
508
566
|
try {
|
|
509
567
|
configureResolvedCli(cli, {
|
|
510
|
-
ensureMcp:
|
|
568
|
+
ensureMcp: (selectedCli) => {
|
|
569
|
+
try {
|
|
570
|
+
ensureCliMcpConfigured(selectedCli);
|
|
571
|
+
}
|
|
572
|
+
catch (error) {
|
|
573
|
+
if (targetedOpenCodeLaunch && selectedCli === 'opencode') {
|
|
574
|
+
throw new OpenCodeTargetedLaunchConfigError(active?.droneLabel ?? '<unknown>', active?.worktree ?? process.cwd());
|
|
575
|
+
}
|
|
576
|
+
throw error;
|
|
577
|
+
}
|
|
578
|
+
},
|
|
511
579
|
addClaudeProjectSessionStartHook: () => {
|
|
512
580
|
// gh#673 P2 (WI-1): the orientation hook lives PROJECT-LOCAL in
|
|
513
581
|
// <root>/.claude/settings.local.json — ensured on every bare
|
|
@@ -523,6 +591,8 @@ function ensureResolvedCliConfigured(cli) {
|
|
|
523
591
|
});
|
|
524
592
|
}
|
|
525
593
|
catch (err) {
|
|
594
|
+
if (err instanceof OpenCodeTargetedLaunchConfigError)
|
|
595
|
+
throw err;
|
|
526
596
|
console.error(`${consolePrefix()}${chalk.yellow(`warning: ${label} integration check failed: ${err?.message ?? err}`)}`);
|
|
527
597
|
}
|
|
528
598
|
try {
|
|
@@ -544,6 +614,11 @@ function isEntryInvocation() {
|
|
|
544
614
|
}
|
|
545
615
|
if (isEntryInvocation()) {
|
|
546
616
|
main().catch((error) => {
|
|
617
|
+
if (error instanceof LaunchSeatIdentityChangedError ||
|
|
618
|
+
error instanceof OpenCodeTargetedLaunchConfigError) {
|
|
619
|
+
process.stderr.write(`${error.message}\n`);
|
|
620
|
+
process.exit(1);
|
|
621
|
+
}
|
|
547
622
|
console.error(`${consolePrefix()}${chalk.red(`\n◼ Error: ${error.message}\n`)}`);
|
|
548
623
|
process.exit(1);
|
|
549
624
|
});
|