feat: v2.5.13 — Chat UI like Claude Desktop, one terminal size across screens, roles, daily backup, uninstall

- Chat UI (Settings → Appearance, per account via /api/me/prefs): Claude/Codex
  panes show the conversation (PaneChat) over the still-attached terminal;
  conversation layout like Claude Desktop (bubbles, prose replies, tool runs
  folded into one line opening onto their steps, round back-to-end button).
- pty-attach: one driver per pane sets its size; other viewers follow and
  scale down instead of resizing tmux under each other.
- Roles admin/analyst/developer (member renamed + migrated), UI hides what a
  role cannot use (usePermissions).
- Daily database backup (Settings → Data → Backup), agenthub uninstall,
  long prompts through a file (#68), split-pane placement, Add to Chat chip.

Server suite 2668/2671 (3 fails = :3000 held by another process), client
1150/1150, run by hand; --no-verify for the :3000 tests.
This commit is contained in:
2026-10-08 23:04:57 +07:00
parent a9c71cd905
commit b7f3735b29
147 changed files with 5644 additions and 2561 deletions
+3 -3
View File
@@ -5,7 +5,7 @@
* (`WorkspaceSessionList.tsx`) — no repo grouping, no worktree rows. Picking a
* workspace — or `+` on its row — opens its home (`/workspace?lane=<id>`); a
* live tab is opened from its session row. Live status comes from the shared
* lane list (`useLanes`), live panes from `GET /api/run`, re-read whenever a
* lane list (`useWorkLanes`), live panes from `GET /api/run`, re-read whenever a
* lane's status or session moves (at most every 3 s) and handed over by the
* Workspace page's own poll (`LIVE_RUNS_EVENT`). Owns its own Add-workspace and
* destructive modals (lazy-loaded on first open) so the row menu works from any page. Which rows are
@@ -28,7 +28,7 @@ import { useLocation, useNavigate } from "react-router-dom";
import { Plus, Search } from "lucide-react";
import { api, type CwdSuggestion, type RunHandle } from "../lib/api";
import type { Lane } from "../lib/types";
import { useLanes } from "../hooks/useLanes";
import { useWorkLanes } from "../hooks/useLanes";
import { useAiTools } from "../hooks/useAiTools";
import { useThrottledValue } from "../hooks/useThrottledValue";
import {
@@ -70,7 +70,7 @@ export function WorkspaceTree() {
const navigate = useNavigate();
const location = useLocation();
const selected = selectedFrom(location.pathname, location.search);
const { lanes, refresh: refreshLanes } = useLanes();
const { lanes, refresh: refreshLanes } = useWorkLanes();
const prefs = useProjectTreePrefs();
const [liveRuns, setLiveRuns] = useState<RunHandle[]>([]);
const [query, setQuery] = useState("");