feat: workspace aliases, tab groups of split panes, native path picker (v2.1.0)
- /api/workspaces and `agenthub workspace(s)` / `--workspace` as aliases of /api/lanes and `agenthub lanes` / `--lane`; old names print one stderr note. REPL `help lanes|workspace|workspaces` resolves through the aliases. - A workspace holds up to ten sessions (slots 0-9); every console tab is a group of 1-4 split panes (PaneGroups, agenthub.workspace.paneLayout); parseGroups keeps the stored active tab when an earlier one is dropped. - Browse button beside path fields: POST /api/lanes/pick-path opens the OS picker on the server's desktop — loopback only and no forwarding header (EREMOTE), a display failure is ENODIALOG not a Cancel, the dialog is killed when the request closes, a folder field falls back to the in-app browser on any failure. - Changes rail counts chip, image viewer (/git/raw), status bar session counts and per-day cost (`date=` on /api/pricing/cost). - /agenthub-open and /agenthub-doctor run from the INSTALLED build (supersededBy), doctor offers fixes behind two confirmations; plugin-open treats a locked bootstrap as non-fatal. - New-terminal shell waits for the first attach (issue #55). - repo-onboarding / debug-live-issue skills removed. - OpenAPI: pick-path, lane/date on /pricing/cost, tool on /run/history, /api/workspaces mount.
This commit is contained in:
+18
-6
@@ -22,8 +22,8 @@
|
||||
* Spawns `claude`, `codex` or `agy` (Antigravity) in the tmux pane based on
|
||||
* the tool parameter.
|
||||
*
|
||||
* A lane can hold up to four sessions, one per Workspace tab: slot 0 is
|
||||
* `agenthub-lane-<laneId>` (the lane's own `run_id`), slots 1–3 are
|
||||
* A lane can hold up to ten sessions (`MAX_PANE_SLOT`): slot 0 is
|
||||
* `agenthub-lane-<laneId>` (the lane's own `run_id`), slots 1–9 are
|
||||
* `agenthub-lane-<laneId>-<slot>`. A slot holds an AI tool (`spawnRun`) or a
|
||||
* plain shell (`spawnShell`, a Terminal tab).
|
||||
*
|
||||
@@ -43,9 +43,10 @@ try {
|
||||
/* db-less environment, skip persistence */
|
||||
}
|
||||
|
||||
const RUN_ID_RE = /^agenthub-lane-(\d+)(?:-([1-3]))?$/;
|
||||
/** Highest pane slot a lane may use (the Workspace's 4-pane grid is 0–3). */
|
||||
const MAX_PANE_SLOT = 3;
|
||||
const RUN_ID_RE = /^agenthub-lane-(\d+)(?:-([1-9]))?$/;
|
||||
/** Highest pane slot a lane may use: ten sessions per workspace, 0–9 (the
|
||||
* Workspace groups them into tabs of up to four split panes each). */
|
||||
const MAX_PANE_SLOT = 9;
|
||||
const EFFORT_LEVELS = new Set(["low", "medium", "high", "xhigh", "max"]);
|
||||
// `auto` is the CLI's own default-ish mode (`claude --permission-mode auto`):
|
||||
// it asks only for what its classifier reads as risky. `default` is kept for
|
||||
@@ -529,7 +530,18 @@ function spawnShell({ laneId, slot = 0, cwd }) {
|
||||
...(process.env.PATH ? { PATH: process.env.PATH } : {}),
|
||||
...desktopEnv(),
|
||||
};
|
||||
tmux.newSession({ name: id, cwd, argv: [], env });
|
||||
// The session is born 80×24 and only takes the browser's size when the pane
|
||||
// attaches. A shell started at once printed its prompt at 80 columns (a long
|
||||
// cwd wrapped), and readline's redraw after the resize left the cursor on top
|
||||
// of the prompt (issue #55). So wait until a client is attached — 2 s at
|
||||
// most — then exec the login shell tmux would have run (tmux sets SHELL in the
|
||||
// pane). Not "the first SIGWINCH": the scrollbar `enableMouse` turns on
|
||||
// resizes the pane before any client is there. A tmux that cannot answer
|
||||
// ends the wait at once, i.e. the old behaviour.
|
||||
const waitForSize =
|
||||
"i=0; while [ \"$(tmux display -p -t \"$TMUX_PANE\" '#{session_attached}' 2>/dev/null)\" = 0 ]" +
|
||||
' && [ $i -lt 20 ]; do sleep 0.1; i=$((i+1)); done; exec "$SHELL" -l';
|
||||
tmux.newSession({ name: id, cwd, argv: ["sh", "-c", waitForSize], env });
|
||||
dashboardRuns?.recordRun({
|
||||
id,
|
||||
sessionId: null,
|
||||
|
||||
Reference in New Issue
Block a user