Skip to content

Commit ea8e1ea

Browse files
authored
Merge pull request #4 from MattMagg/001-session-ui-overhaul
feat(dashboard): MVP Session UI Overhaul
2 parents 91c408c + c25ee63 commit ea8e1ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+5072
-451
lines changed

.agent/rules/specify-rules.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
Auto-generated from all feature plans. Last updated: 2026-02-22
44

55
## Active Technologies
6+
- TypeScript, React, Next.js (App Router) + RPC v11, @tanstack/react-query, shadcn/ui, Tailwind CSS (001-session-ui-overhaul)
7+
- N/A for this feature (Client-side state + Gateway events) (001-session-ui-overhaul)
68

79
- TypeScript / Node.js + Next.js (App Router), React, `lucide-react`, `shadcn/ui`, Tailwind CSS, `zod`, `trpc`, `@xyflow/react` (003-agent-orchestration-ui)
810

@@ -22,6 +24,7 @@ npm test && npm run lint
2224
TypeScript / Node.js: Follow standard conventions
2325

2426
## Recent Changes
27+
- 001-session-ui-overhaul: Added TypeScript, React, Next.js (App Router) + RPC v11, @tanstack/react-query, shadcn/ui, Tailwind CSS
2528

2629
- 003-agent-orchestration-ui: Added TypeScript / Node.js + Next.js (App Router), React, `lucide-react`, `shadcn/ui`, Tailwind CSS, `zod`, `trpc`, `@xyflow/react`
2730

docs/plans/2026-02-22-openclaw-fresh-install-design.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ Based on [Configuration Reference](https://docs.openclaw.ai/gateway/configuratio
5555

5656
Per security docs: loopback binding keeps Control UI inaccessible from the network. Port 18789 is the documented default. v2026.2.21 now sets security headers on gateway HTTP responses automatically.
5757

58+
**Device auth bypass** (required for Node.js Control UI clients like Claw Dash):
59+
60+
```json5
61+
{
62+
"gateway": {
63+
"controlUi": {
64+
"allowInsecureAuth": true,
65+
"dangerouslyDisableDeviceAuth": true
66+
}
67+
}
68+
}
69+
```
70+
71+
v2026.2.21 requires WebCrypto device identity for Control UI connections. Node.js WebSocket clients (Claw Dash, probes) cannot provide device identity — they lack browser WebCrypto context. `dangerouslyDisableDeviceAuth` disables this check. Safe on loopback with token auth. `allowInsecureAuth` alone has known bugs ([#1679](https://github.com/openclaw/openclaw/issues/1679), [#2248](https://github.com/openclaw/openclaw/issues/2248)) — both flags are needed.
72+
5873
### Exec
5974

6075
```json5
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<role>
2+
You are an elite Frontend Architect, UX Researcher, and React/Next.js Engineer. Your expertise lies in designing and building ultra-premium, highly functional command centers and AI chat interfaces.
3+
</role>
4+
5+
<context>
6+
The current Claw Dash chat session UI (`/sessions`) suffers from severe UX regressions and missing features, as detailed in `ui-audit-report.md` and `docs/plans/2026-02-21-claw-dash-post-audit-improvements.md`.
7+
8+
The primary issues are:
9+
1. **Missing Streaming:** The UI waits for final payloads and polls aggressively, completely lacking optimistic rendering and animated typing/thinking indicators.
10+
2. **Broken Session Metadata:** The sidebar shows unparsed string metadata instead of human-readable conversation titles, and the active session header displays raw database IDs.
11+
3. **Unhandled Payloads:** Expected events like `thinking` blocks crash the parser and render as glaring red JSON error boundaries instead of polished accordion components.
12+
4. **Tag Bleed:** Internal routing tags (e.g., `[[reply_to_current]]`) bleed into the user-facing message feed.
13+
5. **Outdated Composer:** The active chat input lacks robust model selection, thinking level toggles, and attachment support, falling severely behind the pre-session page's layout.
14+
</context>
15+
16+
<objective>
17+
Your objective is to create a comprehensive, world-class documentation suite for overhauling and perfecting the Claw Dash chat session UI. You must design an architectural blueprint and UX specification that permanently resolves the known issues while elevating the interface to a premium standard.
18+
</objective>
19+
20+
<instructions>
21+
Follow these steps to complete your mission:
22+
23+
1. **Perform a Live Audit:**
24+
- Launch the local development server by running `npm run dev` in the `claw-dash` root directory.
25+
- Utilize your browser subagent to navigate to `http://localhost:3939/sessions`.
26+
- Interact with the UI: start a session, send messages, and physically observe the lack of streaming, the metadata errors, and layout discrepancies.
27+
28+
2. **Conduct Benchmark Research:**
29+
- Comprehensively examine the frontend codebases, component architectures, and styling layouts of the following local reference repositories:
30+
- `/Users/matthewmaggio/open-webui`
31+
- `/Users/matthewmaggio/anything-llm`
32+
- `/Users/matthewmaggio/agent-chat-ui`
33+
- Extract state-of-the-art layout paradigms, streaming implementations, and styling best practices from these repositories that can be adapted for Claw Dash.
34+
35+
3. **Investigate & Plan Architecture:**
36+
- Leverage your tools (`context7`, `tavily`, `shadcn ui`) and skills (`frontend design`, `ralph loop`) to design optimal architectural fixes.
37+
- Note: Use your best judgment unconditionally. Do not wait for explicit, step-by-step tool instructions; proactively explore the codebase and external resources.
38+
39+
4. **Generate the Final Documentation Suite:**
40+
- Write a definitive, execution-ready documentation suite that details exactly how to overhaul the chat session UI.
41+
- You must dynamically create directories and multiple markdown files (e.g., splitting into component specs, streaming state management, premium styling guidelines) to maximize clarity and comprehensiveness.
42+
- The final output must leave absolute zero ambiguity for the implementing engineer.
43+
</instructions>
44+
45+
<constraints>
46+
- **Aesthetics Are Paramount:** The design must utilize a premium dark-mode aesthetic featuring deep glassmorphism, subtle interaction rings, and fluid micro-animations. Plain or default UI libraries are unacceptable without heavy stylistic elevation.
47+
- **Autonomy:** Do not pause the workflow to ask for permission to use tools or explore directories. Act autonomously based on your findings.
48+
- **Strict Adherence:** The streaming implementation strategy must pivot from aggressive polling to either WebSocket subscriptions, Server-Sent Events (SSE), or highly optimized optimistic updates. Document this architecture thoroughly.
49+
</constraints>
50+
51+
<output_format>
52+
- Structure your output as a multi-file documentation suite embedded directly into the project repository (e.g., `docs/chat-ui-overhaul/`).
53+
- Use standard GitHub-Flavored Markdown.
54+
- Utilize standard Mermaid diagrams (`mermaid` code blocks) if mapping out the state lifecycles for streaming text is necessary.
55+
- Provide explicit file paths and diff-ready implementation plans inside your documentation.
56+
</output_format>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Claw Dash Session UI Overhaul — Documentation Suite
2+
3+
> **Status:** Ready for implementation
4+
> **Date:** 2026-02-22
5+
> **Scope:** Complete redesign of `/sessions` and `/sessions/[key]` routes
6+
7+
---
8+
9+
## Document Map
10+
11+
| # | Document | Purpose |
12+
|---|----------|---------|
13+
| 01 | [Audit Findings](./01-AUDIT-FINDINGS.md) | Current-state analysis: confirmed bugs, UX gaps, and architectural debt |
14+
| 02 | [Benchmark Analysis](./02-BENCHMARK-ANALYSIS.md) | Patterns extracted from Open WebUI, AnythingLLM, and Agent Chat UI |
15+
| 03 | [Architecture — Streaming](./03-ARCHITECTURE-STREAMING.md) | Event-driven streaming pipeline: gateway → server → client → DOM |
16+
| 04 | [Architecture — State Management](./04-ARCHITECTURE-STATE.md) | React Query + gateway event subscription + optimistic rendering |
17+
| 05 | [Component Spec — Composer](./05-COMPONENT-COMPOSER.md) | Rich input with model selector, thinking level, attachments, keyboard shortcuts |
18+
| 06 | [Component Spec — Message Feed](./06-COMPONENT-MESSAGE-FEED.md) | Transcript rendering: message bubbles, thinking blocks, tool cards, delegation blocks |
19+
| 07 | [Component Spec — Session Chrome](./07-COMPONENT-SESSION-CHROME.md) | Header, sidebar, metadata display, session lifecycle |
20+
| 08 | [Styling & Design Language](./08-STYLING-DESIGN-LANGUAGE.md) | Color tokens, typography, motion, spatial rules |
21+
| 09 | [Implementation Sequence](./09-IMPLEMENTATION-SEQUENCE.md) | Phased task breakdown with file-level diffs and dependencies |
22+
23+
---
24+
25+
## Guiding Principles
26+
27+
1. **Streaming-first.** Every message renders incrementally. The user never stares at a blank screen.
28+
2. **Event-driven invalidation.** Replace polling-only with gateway event subscriptions for instant updates.
29+
3. **Operator-grade density.** This is a command center, not a consumer chatbot. Information density > whitespace.
30+
4. **Zero unhandled payloads.** Every gateway event type renders a polished component. No red error boundaries in normal operation.
31+
5. **Parity with pre-session form.** Model selection, thinking levels, attachments, and skills must be available mid-conversation, not only at session creation.
32+
33+
## Non-Goals (Out of Scope)
34+
35+
- Multi-gateway profile switching (P3 roadmap item)
36+
- SQLite persistence layer (P3 roadmap item)
37+
- Voice input / STT integration
38+
- Message branching / regeneration (defer to future iteration)
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# 01 — Audit Findings
2+
3+
## Confirmed Issues
4+
5+
### 1. No Streaming — Batch-Only Rendering
6+
7+
**Severity:** Critical
8+
**Location:** `transcript.tsx`, `sessions/[key]/page.tsx`
9+
10+
The gateway emits `chat` events with `state: "delta"` for streaming chunks and `state: "final"` for completed messages. The UI ignores deltas entirely. The data path is:
11+
12+
1. `sessions/[key]/page.tsx` calls `trpc.sessions.history.queryOptions()` — a standard React Query poll.
13+
2. React Query uses a 5-second `staleTime` (set in `TRPCReactProvider`).
14+
3. `sendMutation.onSuccess` triggers `queryClient.invalidateQueries` to refetch history.
15+
16+
**Result:** After the user sends a message, they see nothing until the full response completes and the next poll fires. For long-running agent tasks (tool calls, delegations), this can mean 30+ seconds of dead silence.
17+
18+
**Root cause:** The server receives gateway `chat` events via `gateway.on("event", ...)` in `server.ts`, but only feeds them into the `EventCollector` for the activity stream. No mechanism exists to push delta events to the client.
19+
20+
---
21+
22+
### 2. Broken Session Metadata Display
23+
24+
**Severity:** High
25+
**Location:** `session-sidebar.tsx` line 101, `session-workspace.tsx` line 134-135
26+
27+
**Sidebar:** The title computation `s.label ?? s.derivedTitle ?? s.displayName ?? s.key` works correctly in code, but `label`, `derivedTitle`, and `displayName` are often `undefined` from the gateway. The fallback `s.key` renders raw keys like `agent:main:1771793471876`.
28+
29+
**Header:** The workspace header displays:
30+
```tsx
31+
<h2>{session.label ?? session.key}</h2>
32+
<span className="font-mono">{session.key}</span>
33+
```
34+
When `label` is undefined, the h2 shows the raw key. The monospace key always shows below it — no conditional rendering.
35+
36+
**Root cause:** The gateway's `sessions.list` response only populates `derivedTitle` when `includeDerivedTitles: true` is passed (which it is in `[key]/page.tsx`, but the sidebar data comes from a different query instance). Additionally, new sessions created via `chat.send` don't have a title until the gateway auto-derives one after the first exchange.
37+
38+
---
39+
40+
### 3. Unhandled Payload Types → Red Error Boundaries
41+
42+
**Severity:** High
43+
**Location:** `normalize-content.ts`, `transcript.tsx` EventRenderer `default` case
44+
45+
The `parseEvents()` function handles: `tool_use`, `tool_result`, text, `<think>` blocks, `tool_calls`, delegations, and approvals. Any object that doesn't match these patterns falls through to `type: "unknown"`, which renders as:
46+
47+
```tsx
48+
<div className="bg-red-950/10 border border-red-900/30">
49+
<div className="text-red-400 font-semibold">Unrecognized Payload</div>
50+
<CodeBlock language="json" value={JSON.stringify(event.payload)} />
51+
</div>
52+
```
53+
54+
**Known unhandled types:**
55+
- `thinking` blocks sent as `{ type: "thinking", thinking: "..." }` (Claude extended thinking format, distinct from `<think>` tags)
56+
- `text` blocks sent as `{ type: "text", text: "..." }` within content arrays — these ARE handled, but only when the `text` key is present. If the block has `type: "text"` without a `text` key, it falls through.
57+
- Status/progress events from tool execution
58+
- `signature` blocks (`{ type: "signature", ... }`)
59+
60+
---
61+
62+
### 4. Tag Bleed — Internal Routing Tags in User Feed
63+
64+
**Severity:** Medium
65+
**Location:** `normalize-content.ts` `parseTextWithThoughts()`
66+
67+
The text parsing function splits on `<think>...</think>` but does not strip other internal tags. The gateway prepends routing tags like `[[reply_to_current]]` or `[[agent:delegated_task]]` to message content for orchestration purposes. These render as visible text in the transcript.
68+
69+
**Fix required:** A tag-stripping pass before rendering text events. Pattern: `[[...]]` at the start of text content.
70+
71+
---
72+
73+
### 5. Composer Feature Gap Between Pre-Session and In-Session
74+
75+
**Severity:** High
76+
**Location:** `controls-bar.tsx` vs `sessions/page.tsx`
77+
78+
**Pre-session form (`/sessions`)** offers:
79+
- Agent selection dropdown
80+
- Model override (sonnet-4.6, opus-4.6, haiku-4.5, gpt-5.2, gpt-5.3-codex)
81+
- Workflow template (scaffold, pr-review, atomic-commit)
82+
- Skill profile (web-tavily, mcp-local, all)
83+
- File attachments with drag-and-drop
84+
- 4-level thinking selector (Default, Low, Medium, High) — segmented control
85+
86+
**In-session composer (`/sessions/[key]`)** offers:
87+
- Textarea
88+
- "Basic" / "Deep Think" buttons (call `sessions.patch` — different mechanism than send-time params)
89+
- Abort button
90+
- Send button
91+
92+
**Missing from in-session:** Model override, workflow, skills, attachments, granular thinking levels, any visual indication of current model/thinking state.
93+
94+
---
95+
96+
### 6. Additional UX Gaps (Discovered via Code Review)
97+
98+
**No scroll-to-bottom button.** Auto-scroll fires on `messages.length` change (line 106-108 in `transcript.tsx`), but there's no button to re-engage auto-scroll after the user scrolls up.
99+
100+
**No streaming/loading indicator.** When `sendMutation.isPending`, the Send button says "Sending..." but nothing appears in the transcript until the full response arrives.
101+
102+
**No message timestamps by default.** Timestamps exist but are hidden with `opacity-0 group-hover:opacity-100` — invisible unless hovering.
103+
104+
**No copy/action buttons on messages.** No copy-to-clipboard, no message regeneration, no edit-and-resubmit.
105+
106+
**Markdown rendering is minimal.** `renderMessageContent()` only handles code blocks (triple-backtick). Inline code, bold, italic, links, lists, tables, and LaTeX are all rendered as plain text.
107+
108+
**No empty state for Context tab.** The `ActiveContextPanel` shows "No active background operations" with a wrench icon, but gives no guidance on what to expect.
109+
110+
**Right panel is always visible.** The 320px right panel (Context/Config/Orchestration) is hardcoded with no collapse/hide mechanism, reducing transcript width on smaller screens.
111+
112+
---
113+
114+
## Summary Matrix
115+
116+
| Issue | Severity | Category | Fix Complexity |
117+
|-------|----------|----------|---------------|
118+
| No streaming | Critical | Architecture | High — requires event subscription pipeline |
119+
| Broken metadata | High | Data flow | Medium — query consolidation + title derivation |
120+
| Unhandled payloads | High | Parsing | Low — extend `parseEvents()` |
121+
| Tag bleed | Medium | Parsing | Low — regex strip before render |
122+
| Composer gap | High | Component | Medium — port pre-session controls to in-session |
123+
| Missing scroll button | Medium | UX | Low |
124+
| No loading indicator | High | UX | Low-Medium |
125+
| No message actions | Medium | UX | Medium |
126+
| Minimal markdown | High | Rendering | Medium — integrate react-markdown |
127+
| Non-collapsible panel | Medium | Layout | Low |

0 commit comments

Comments
 (0)