feat(ui): AI Tools modal, one-button lane tool picker, AgentHub settings in Overview, markdown preview

- AI Tools moves from a Settings section into a modal behind a button at the
  Settings tab bar's right edge (AiToolsModal, `actions` on PageTabs,
  /settings#ai-tools); rows get an enable switch, Default badge, and an
  Update button for every tool whose catalog names an updater (no version
  lookup on open); not-installed tools fold behind a disclosure, a finished
  job's log folds to one line; shared AiToolIcon
- codex updates through its own `codex update`, openclaw/hermes gain
  `update --yes`; update-all runs every installed updater and skips an npm
  one only when npm does not manage the binary
- Add-lane tool picker is one button showing the chosen tool that opens the
  enabled tools as buttons
- Claude Code / Codex AgentHub sub-tab folded into Overview (home editor,
  hooks, pricing); the path list drops CLAUDE_HOME/CODEX_HOME;
  HomeDirSetting shows the saved value only while the field differs
- Preview/Raw toggle for markdown files in the config FileViewer and the
  Changes panel's whole-file view (MarkdownPreview: react-markdown +
  remark-gfm, raw HTML never run, frontmatter as a code block)
- docs and the CLAUDE.md marker updated
This commit is contained in:
2026-10-01 10:11:43 +07:00
parent 058c574138
commit c5aba094bd
55 changed files with 2985 additions and 853 deletions
+17 -4
View File
@@ -188,10 +188,12 @@ client/
│ │ ├── RemoteSources.tsx # Remote Data Sources settings panel (SSH multi-machine collection)
│ │ ├── SessionToolBadge.tsx # The CLI that produced a non-Claude session, by its AI Tools label (nothing for Claude)
│ │ ├── settings/ # Settings panels, among them:
│ │ │ ├── AiToolsModal.tsx # AI Tools dialog, opened from the Settings tab bar's right edge
│ │ │ ├── AiToolsSettings.tsx # Its body: installed/available CLIs, enable/default, install/update
│ │ │ ├── PricingSettings.tsx # Model Pricing table, `vendor` filter + Show all models
│ │ │ ├── ClaudeAgentHubSettings.tsx # Claude Code → AgentHub: pricing, hook status, CLAUDE_HOME
│ │ │ ├── ClaudeAgentHubSettings.tsx # Claude Code → Overview: CLAUDE_HOME, hook status, pricing
│ │ │ ├── HomeDirSetting.tsx # CLAUDE_HOME / CODEX_HOME editor (env-owned warning)
│ │ │ ├── CodexHooksSettings.tsx # Codex → AgentHub → Codex hooks card
│ │ │ ├── CodexHooksSettings.tsx # Codex → Overview → Codex hooks card
│ │ │ └── AntigravityHooksSettings.tsx # Antigravity → Antigravity hooks card
│ │ └── workflows/ # Workflows page panels: own-pipeline stats + D3 analytics (11 files)
│ │
@@ -247,7 +249,7 @@ graph TB
Detail[SessionDetail<br/>agent hierarchy + timeline]
Feed[ActivityFeed<br/>streaming event log]
Workflows[Workflows<br/>Lane pipelines + D3 analytics]
Settings[SettingsHub<br/>Dashboard tab: appearance + notifications + data<br/>Claude Code / Codex → AgentHub, Antigravity:<br/>each tool's pricing + hooks]
Settings[SettingsHub<br/>Dashboard tab: appearance + notifications + data<br/>Claude Code / Codex → Overview, Antigravity:<br/>each tool's pricing + hooks]
App --> Layout
Layout --> Dashboard & Sessions & Detail & Feed & Workflows & Settings
@@ -293,7 +295,7 @@ sequenceDiagram
The client uses **local component state** and **React hooks** for state management. No global state library (Redux, Zustand) is used to keep the architecture simple. The one small exception is the **data-scope store** (`lib/dataScope.ts`): a lightweight app-wide store holding the current set of data sources (`local` plus any configured [Remote Data Sources](../server/README.md#remote-data-sources)). Pages read it and append `?sources=` to their API requests, so a single selector narrows the whole app to one or more machines' data. Remote sources are managed from the Settings page via the `RemoteSources` component (`components/RemoteSources.tsx`), which drives the `/api/remote-sources` CRUD/test/sync endpoints and reflects live `remote_source.status` WebSocket updates. When a sync finishes, stats pages refetch via `lib/remoteDataEvents.ts` (`remote_data.updated`, `remote_source.status` with `ok`, or remote `import.progress` complete).
**Cursor sessions (informational):** Settings surfaces a subtle note on the CLAUDE_HOME (Settings → Claude Code → AgentHub), Import History, and Remote Data Sources panels — **Cursor** agent sessions count too because Cursor stores transcripts under the same `~/.claude` paths as Claude Code locally (and on synced remotes).
**Cursor sessions (informational):** Settings surfaces a subtle note on the CLAUDE_HOME (Settings → Claude Code → Overview), Import History, and Remote Data Sources panels — **Cursor** agent sessions count too because Cursor stores transcripts under the same `~/.claude` paths as Claude Code locally (and on synced remotes).
### State Strategy
@@ -763,6 +765,17 @@ closes. Consequences worth knowing:
expanding a truncated **number** inside a line of text, but draws the same
surface so the two read as one thing.
#### MarkdownPreview (`components/MarkdownPreview.tsx`)
A `.md`/`.markdown`/`.mdx` file (`isMarkdown`) rendered for reading with
`react-markdown` + `remark-gfm` (tables, task lists, strikethrough). It sits
behind a **Preview** / **Raw** toggle in two places: the config explorer's
`FileViewer` and the Changes panel's whole-file view (`lane-file-preview`,
reset to Raw on every file switch; the editor still opens from Raw). Raw HTML
in the file is shown as text, never run (no `rehype-raw`), links open in a new
tab, and a leading YAML frontmatter block is shown as a code block. Styles are
the `.md-preview` rules in `index.css`, built from theme tokens.
---
## Utilities