Files
AgentHub/docs/plans/workspace-redesign/02-settings.md
T
nntrivi2001 a6bd33bcff feat: workspaces own their sessions; desktop parity; sidebar and settings cleanup
Workspace sessions (docs/plans/desktop-parity, phases 1-5 and 7):
- sessions.lane_id: a workspace lists only the sessions its panes held,
  stamped by bindRunSession (first writer wins, nested `claude -p`
  excluded); GET /api/sessions?lane=&archived=
- session row state dot, double-click rename, archive (sessions.archived_at,
  hides only); the activity bar's duplicate Sessions tab removed
- Fork beside Resume (--fork-session, Claude only), Ctrl/Cmd+click a live
  session opens it in a second pane, a diff line's comment is pasted into
  the workspace's last-focused pane (lib/panePaste.ts)

dashboard_runs stability:
- a pane's previous run is archived as <pane>@<started_at> instead of being
  overwritten by INSERT OR REPLACE
- a run is flagged abandoned only once its tmux session is gone, at boot and
  on the run-heal beat (panes outlive a server restart)

UI:
- sidebar: no footer, language or theme block; small collapse button in the
  brand corner; version + update check in the connection details modal, a
  status-bar dot while a release is out; language in Settings -> General
- one Switch component for every switch, the themed Checkbox for every
  checkbox (no native checkboxes)

Also: AI Tools catalog trimmed to 10 built-ins (custom-file prompt modes
tested through fixtures), and the workspace plans under docs/plans/ (the
multi-user server plan lives in the AgentHub-Server repo).
2026-10-02 13:19:50 +07:00

151 lines
8.7 KiB
Markdown

# Phase 2 — Settings as a full-page grouped navigation
_One PR, after phase 1._
## Goal
Replace the horizontal `PageTabs` bar on `/settings` with a left navigation
grouped under small uppercase headings, one section per route, a search box
that filters sections, and consistent row primitives — the structure in
`reference/orca-settings1.png` / `orca-settings-agents.png` /
`orca-settings-scrolled.png`, in AgentHub's own tokens.
## Non-goals
- No new settings. Every control that exists today is kept, moved, and
reachable from search. (One exception: the worktree-visibility toggles from
phase 1 get their first proper home here.)
- No theme change. No new dependency.
- No change to any server setting route.
## 1. Routes
`App.tsx`: `settings` → `settings/:section?`. `SettingsHub.tsx` reads
`:section`; unknown or missing ⇒ redirect to `settings/general`. The old
`?tool=<id>` query is honoured for one release: `?tool=claude-code` ⇒
`/settings/agents/claude-code`, `?tool=ai-router` ⇒ `/settings/ai-router`, and
`#ai-tools` ⇒ `/settings/agents` with the catalog modal open. Every in-app link
that builds a settings URL (`AddLaneModal`'s AI Tools link, the Claude
tab's cross-links, `Sidebar` nav) is updated to the path form.
Section ids are stable strings (they are URLs and i18n keys):
| Group (i18n `settingsNav.group.*`) | Section id | Content = today's component |
| --- | --- | --- |
| **General** | `general` | `Settings.tsx` sections: `lanesSection` (renamed "Workspaces": housekeeping) + `data` (import, remote sources, clear data) + `about` |
| | `appearance` | `AppearanceSettings` |
| | `notifications` | `Settings.tsx` `notifications` + `alertsHub` (`AlertsNotifications`, `WebhookSettings`) |
| **Agents** | `agents` | `AiToolsSettings` inline (the modal's content as a page; `AiToolsModal` stays for the Add-workspace link) |
| | `agents/claude-code` | `CcConfig` (its own sub-tabs stay inside the page) |
| | `agents/codex` | `CodexConfig` |
| | `agents/<catalog id>` | `AiToolConfig toolId` — one entry per installed, enabled tool without a `launcher` (same rule as today's `catalogTabs`) |
| **Routing** | `ai-router` | `AiRouterConfig` |
| | `pricing` | `PricingSettings` with a vendor filter for *all* vendors (today it is embedded per tool; keep those embeds too — this page is the all-vendors view) |
| **Git** | `git-credentials` | `GitCredentialsConfig` |
| | `worktrees` | **new** `WorktreeVisibilitySettings`: "Show untracked worktrees" switch; per-source rows `.claude/worktrees/*` (Show/Hide), AgentHub-managed (`LANES_ROOT`) (Show/Hide); writes the phase-1 localStorage key |
| **Projects** | `projects/<encoded root>` | **new** `ProjectSettings`: read-only project card (root, main branch, worktree count), its workspaces (link to each), the per-project override of the worktree sources above (`hideSources` keyed by root), and "Forget all workspaces of this project" (loops `POST …/remove`, confirm modal listing them) |
A tool section is hidden while that tool is disabled (same `aiTools.byId(...).enabled` check as today).
## 2. Layout
```
┌ sidebar (app) ┬──────────────────────────────────────────────────────────┐
│ │ ← Back to Workspace │
│ │ [🔍 Search settings Ctrl+F] │
│ │ │
│ │ GENERAL │ General │
│ │ ⚙ General │ Workspace housekeeping, data, about. │
│ │ ◐ Appearance │ ───────────────────────────────────── │
│ │ 🔔 Notifications│ ┌ card ─────────────────────────────┐ │
│ │ AGENTS │ │ Housekeeping │ │
│ │ ▣ AI tools │ │ Run housekeeping [Dry run][Run]│ │
│ │ ✳ Claude Code │ ├───────────────────────────────────┤ │
│ │ ◎ Codex │ │ Data │ │
│ │ ▲ Antigravity │ │ Import history … │ │
│ │ ROUTING … │ └───────────────────────────────────┘ │
│ │ PROJECTS │ │
│ │ ◈ agenthub │ │
└───────────────┴──────────────────┴─────────────────────────────────────────┘
```
- The settings nav is a second column **inside** the page (`w-56`, sticky,
own scroll), not the app sidebar. The app sidebar stays as it is.
- "← Back to Workspace" is a plain link to `/workspace` (keeps `?ws` from
localStorage).
- Content column: `max-w-3xl`, section title `text-2xl font-semibold`, one-line
description `text-sm text-fg-muted`, hairline, then **one card per subsection**
(`.card` as today). Do not nest cards.
- Mobile (`< md`): the nav becomes a `<select>` above the content.
## 3. Primitives (`client/src/components/settings/SettingsRow.tsx`)
```tsx
<SettingsSection title description> // h3 + muted description inside a card
<SettingsRow label description control alignTop?> // 2 columns: label+desc | control (shrink-0)
<SettingsSwitchRow label description checked onChange disabled? />
<SettingsSegmented options value onChange /> // role="radiogroup", existing button styles
```
Every control already in `Settings.tsx`, `AppearanceSettings.tsx`,
`ClaudeAgentHubSettings.tsx`, `CodexHooksSettings.tsx`,
`AntigravityHooksSettings.tsx`, `AiToolConfig.tsx` is re-wrapped in these
rows. `CcConfig.tsx` (172 KB) and `CodexConfig.tsx` keep their internal layout
in this phase — only their outer frame changes. Rows: `py-3` with a
description, `py-2` without; divider `border-b border-border/60` between
rows, none after the last.
## 4. Search
`client/src/lib/settingsSearch.ts`:
```ts
interface SettingsEntry { section: string; title: string; description?: string; keywords?: string[] }
rankSettings(query, entries): { section: string; score: number }[]
```
Scoring (lowercase; exact > prefix > substring): section title 900/850/800,
entry title 700/650/600, description 500/450/400, keywords 300/250/200. Each
section registers its entries in a static `SETTINGS_INDEX` array (one per
`SettingsRow` label at minimum; i18n-resolved at render). While the query is
non-empty the nav shows only matching sections (groups with no match hidden),
the first match is focused, Enter opens it; Esc clears. `Ctrl+F` / `Cmd+F`
focuses the box when the settings page has focus (do not steal it from a
terminal — `/settings` has none, so a plain keydown listener on the page root
is enough).
## 5. i18n
`settings.json`: `settingsNav.group.{general,agents,routing,git,projects}`,
`settingsNav.section.*` (title + description per id), `search.placeholder`,
`search.noMatch`, `back`, `worktrees.*`, `project.*`. Remove `tools.*` keys
that no longer render (keep `tools.label` if `AiToolsModal` still uses it).
## 6. Tests
- `SettingsHub.test.tsx`: route → section, legacy `?tool=` redirect, hidden
tool section when disabled, mobile select.
- `settingsSearch.test.ts`: ranking order, empty query, no match.
- `WorktreeVisibilitySettings.test.tsx`: writes the phase-1 key, per-project
override.
- Existing panel tests unchanged except their mount path.
- Snapshots: Settings screens regenerate once.
## 7. Docs
`docs/LANES.md` (worktree visibility, per-project settings), `README.md`
(settings tour), `client/README.md` (route list, primitives), `CLAUDE.md`
marker: "Settings is `/settings/:section` with a grouped nav; a tool's own
settings live under `agents/<id>`; the whole-page search index is
`SETTINGS_INDEX`".
## Acceptance
- Every control reachable before is reachable after (walk `Settings.tsx`'s
section list and each tool tab, tick them off in the PR body).
- `/settings?tool=codex` lands on `/settings/agents/codex`.
- Typing "pricing" in search shows Routing → Pricing and the Claude/Codex
pages (both embed the table); Enter opens the first.
- Keyboard: Tab order follows the visual order; `Ctrl+F` focuses search.
- Suites + headers + snapshots green; before/after screenshots.