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:
@@ -12,6 +12,10 @@
|
||||
* new lane's own live session for its slot, or an empty pane — never the
|
||||
* previous lane's terminal. `attachRequest` (a run picked in the sidebar or a
|
||||
* tab) attaches to that tmux session only; nothing is started or resumed.
|
||||
* A Claude or Codex pane also has a Chat view (`PaneChat`): the session's
|
||||
* conversation laid OVER the terminal, which stays mounted and attached under
|
||||
* it. Chat or terminal is the viewer's own Chat UI setting (Settings →
|
||||
* Appearance, `lib/chatUi.ts`, per account) — one choice for every pane.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
|
||||
@@ -23,6 +27,10 @@ import type { RunHandle, RunListResponse } from "../../lib/api";
|
||||
import type { Lane } from "../../lib/types";
|
||||
import { useAiTools } from "../../hooks/useAiTools";
|
||||
import { TerminalView } from "./TerminalView";
|
||||
import { PaneChat } from "./PaneChat";
|
||||
import { useChatUi } from "../../lib/chatUi";
|
||||
|
||||
const CHAT_TOOLS = new Set(["claude", "codex"]);
|
||||
|
||||
export interface LaneConsolePaneProps {
|
||||
lanes: Lane[];
|
||||
@@ -70,6 +78,12 @@ export function LaneConsolePane({
|
||||
// The tool of the run on screen — a session's own, which need not be the
|
||||
// workspace's; the workspace's with no run.
|
||||
const paneTool = handle?.tool ?? currentLane?.tool ?? "claude";
|
||||
const chat = useChatUi();
|
||||
// A run learns its session id after it starts (Codex): the page's poll has it.
|
||||
const chatSession = handle
|
||||
? (activeRuns?.items.find((r) => r.id === handle.id)?.sessionId ?? handle.sessionId)
|
||||
: null;
|
||||
const chatable = !!handle && !!chatSession && CHAT_TOOLS.has(handle.tool);
|
||||
|
||||
useEffect(() => {
|
||||
onHasActiveRunChange?.(handle !== null);
|
||||
@@ -173,11 +187,22 @@ export function LaneConsolePane({
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex-1 min-h-0 flex flex-col">
|
||||
<div className="relative flex-1 min-h-0 flex flex-col">
|
||||
{/* Over the terminal, never instead of it: unmounting would drop the attach. */}
|
||||
{chatable && chat && (
|
||||
<div className="absolute inset-0 z-20 flex flex-col bg-surface-0">
|
||||
<PaneChat
|
||||
runId={handle.id}
|
||||
sessionId={chatSession}
|
||||
tool={handle.tool}
|
||||
cwd={handle.cwd || currentLane?.cwd || ""}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<TerminalView
|
||||
runId={handle.id}
|
||||
wsBaseUrl={window.location.origin.replace(/^http/, "ws")}
|
||||
autoFocus={autoFocus}
|
||||
autoFocus={autoFocus && !(chatable && chat)}
|
||||
// The pane died (double Ctrl+C out of `claude`, `exit`, a crash) —
|
||||
// the tab bar moves on (another tab, or the home's prompt box)
|
||||
// rather than leaving a dead terminal the user has to click out of.
|
||||
|
||||
Reference in New Issue
Block a user