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:
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* @file laneOrderStorage.ts
|
||||
* @description Persists the Workspace lane strip's user-chosen card order to
|
||||
* localStorage, the same read/validate/fallback convention as useTheme.ts.
|
||||
* @description Persists the sidebar's user-chosen workspace order to
|
||||
* localStorage, the same read/validate/fallback convention as useTheme.ts, and
|
||||
* holds the drag-to-reorder math the sidebar and the console tab bar share
|
||||
* (the tab bar's own order lives with its tabs, `lib/paneLayout.ts`).
|
||||
*
|
||||
* The order lives in the browser rather than the lanes table on purpose: it is
|
||||
* a per-viewer preference, and nothing
|
||||
@@ -66,3 +68,20 @@ export function moveLane(ids: number[], from: number, to: number): number[] {
|
||||
next.splice(to, 0, ...next.splice(from, 1));
|
||||
return next;
|
||||
}
|
||||
|
||||
/** Where a drop lands: before the first item whose middle (`mids`, on the
|
||||
* drag axis) lies past the pointer, else at the end. Gaps between items —
|
||||
* a workspace's session list, the space between two tabs — count too. */
|
||||
export function insertionIndex(mids: number[], pos: number): number {
|
||||
const i = mids.findIndex((m) => pos < m);
|
||||
return i === -1 ? mids.length : i;
|
||||
}
|
||||
|
||||
/** Moves the item at `from` to just before insertion point `before`. */
|
||||
export function moveBefore<T>(ids: T[], from: number, before: number): T[] {
|
||||
if (from < 0 || from >= ids.length || before < 0 || before > ids.length) return ids;
|
||||
if (before === from || before === from + 1) return ids;
|
||||
const next = [...ids];
|
||||
next.splice(before > from ? before - 1 : before, 0, ...next.splice(from, 1));
|
||||
return next;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user