Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .agent/rules/specify-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Auto-generated from all feature plans. Last updated: 2026-02-22

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

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

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

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

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

Expand Down
15 changes: 15 additions & 0 deletions docs/plans/2026-02-22-openclaw-fresh-install-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,21 @@ Based on [Configuration Reference](https://docs.openclaw.ai/gateway/configuratio

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.

**Device auth bypass** (required for Node.js Control UI clients like Claw Dash):

```json5
{
"gateway": {
"controlUi": {
"allowInsecureAuth": true,
"dangerouslyDisableDeviceAuth": true
}
}
}
```

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.

### Exec

```json5
Expand Down
56 changes: 56 additions & 0 deletions docs/prompt-improver-spec/final-prompts/chat-ui-overhaul.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<role>
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.
</role>

<context>
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`.

The primary issues are:
1. **Missing Streaming:** The UI waits for final payloads and polls aggressively, completely lacking optimistic rendering and animated typing/thinking indicators.
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.
3. **Unhandled Payloads:** Expected events like `thinking` blocks crash the parser and render as glaring red JSON error boundaries instead of polished accordion components.
4. **Tag Bleed:** Internal routing tags (e.g., `[[reply_to_current]]`) bleed into the user-facing message feed.
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.
</context>

<objective>
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.
</objective>

<instructions>
Follow these steps to complete your mission:

1. **Perform a Live Audit:**
- Launch the local development server by running `npm run dev` in the `claw-dash` root directory.
- Utilize your browser subagent to navigate to `http://localhost:3939/sessions`.
- Interact with the UI: start a session, send messages, and physically observe the lack of streaming, the metadata errors, and layout discrepancies.

2. **Conduct Benchmark Research:**
- Comprehensively examine the frontend codebases, component architectures, and styling layouts of the following local reference repositories:
- `/Users/matthewmaggio/open-webui`
- `/Users/matthewmaggio/anything-llm`
- `/Users/matthewmaggio/agent-chat-ui`
- Extract state-of-the-art layout paradigms, streaming implementations, and styling best practices from these repositories that can be adapted for Claw Dash.

3. **Investigate & Plan Architecture:**
- Leverage your tools (`context7`, `tavily`, `shadcn ui`) and skills (`frontend design`, `ralph loop`) to design optimal architectural fixes.
- Note: Use your best judgment unconditionally. Do not wait for explicit, step-by-step tool instructions; proactively explore the codebase and external resources.

4. **Generate the Final Documentation Suite:**
- Write a definitive, execution-ready documentation suite that details exactly how to overhaul the chat session UI.
- 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.
- The final output must leave absolute zero ambiguity for the implementing engineer.
</instructions>

<constraints>
- **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.
- **Autonomy:** Do not pause the workflow to ask for permission to use tools or explore directories. Act autonomously based on your findings.
- **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.
</constraints>

<output_format>
- Structure your output as a multi-file documentation suite embedded directly into the project repository (e.g., `docs/chat-ui-overhaul/`).
- Use standard GitHub-Flavored Markdown.
- Utilize standard Mermaid diagrams (`mermaid` code blocks) if mapping out the state lifecycles for streaming text is necessary.
- Provide explicit file paths and diff-ready implementation plans inside your documentation.
</output_format>
38 changes: 38 additions & 0 deletions docs/session-ui-overhaul/00-INDEX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Claw Dash Session UI Overhaul — Documentation Suite

> **Status:** Ready for implementation
> **Date:** 2026-02-22
> **Scope:** Complete redesign of `/sessions` and `/sessions/[key]` routes

---

## Document Map

| # | Document | Purpose |
|---|----------|---------|
| 01 | [Audit Findings](./01-AUDIT-FINDINGS.md) | Current-state analysis: confirmed bugs, UX gaps, and architectural debt |
| 02 | [Benchmark Analysis](./02-BENCHMARK-ANALYSIS.md) | Patterns extracted from Open WebUI, AnythingLLM, and Agent Chat UI |
| 03 | [Architecture — Streaming](./03-ARCHITECTURE-STREAMING.md) | Event-driven streaming pipeline: gateway → server → client → DOM |
| 04 | [Architecture — State Management](./04-ARCHITECTURE-STATE.md) | React Query + gateway event subscription + optimistic rendering |
| 05 | [Component Spec — Composer](./05-COMPONENT-COMPOSER.md) | Rich input with model selector, thinking level, attachments, keyboard shortcuts |
| 06 | [Component Spec — Message Feed](./06-COMPONENT-MESSAGE-FEED.md) | Transcript rendering: message bubbles, thinking blocks, tool cards, delegation blocks |
| 07 | [Component Spec — Session Chrome](./07-COMPONENT-SESSION-CHROME.md) | Header, sidebar, metadata display, session lifecycle |
| 08 | [Styling & Design Language](./08-STYLING-DESIGN-LANGUAGE.md) | Color tokens, typography, motion, spatial rules |
| 09 | [Implementation Sequence](./09-IMPLEMENTATION-SEQUENCE.md) | Phased task breakdown with file-level diffs and dependencies |

---

## Guiding Principles

1. **Streaming-first.** Every message renders incrementally. The user never stares at a blank screen.
2. **Event-driven invalidation.** Replace polling-only with gateway event subscriptions for instant updates.
3. **Operator-grade density.** This is a command center, not a consumer chatbot. Information density > whitespace.
4. **Zero unhandled payloads.** Every gateway event type renders a polished component. No red error boundaries in normal operation.
5. **Parity with pre-session form.** Model selection, thinking levels, attachments, and skills must be available mid-conversation, not only at session creation.

## Non-Goals (Out of Scope)

- Multi-gateway profile switching (P3 roadmap item)
- SQLite persistence layer (P3 roadmap item)
- Voice input / STT integration
- Message branching / regeneration (defer to future iteration)
127 changes: 127 additions & 0 deletions docs/session-ui-overhaul/01-AUDIT-FINDINGS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# 01 — Audit Findings

## Confirmed Issues

### 1. No Streaming — Batch-Only Rendering

**Severity:** Critical
**Location:** `transcript.tsx`, `sessions/[key]/page.tsx`

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:

1. `sessions/[key]/page.tsx` calls `trpc.sessions.history.queryOptions()` — a standard React Query poll.
2. React Query uses a 5-second `staleTime` (set in `TRPCReactProvider`).
3. `sendMutation.onSuccess` triggers `queryClient.invalidateQueries` to refetch history.

**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.

**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.

---

### 2. Broken Session Metadata Display

**Severity:** High
**Location:** `session-sidebar.tsx` line 101, `session-workspace.tsx` line 134-135

**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`.

**Header:** The workspace header displays:
```tsx
<h2>{session.label ?? session.key}</h2>
<span className="font-mono">{session.key}</span>
```
When `label` is undefined, the h2 shows the raw key. The monospace key always shows below it — no conditional rendering.

**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.

---

### 3. Unhandled Payload Types → Red Error Boundaries

**Severity:** High
**Location:** `normalize-content.ts`, `transcript.tsx` EventRenderer `default` case

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:

```tsx
<div className="bg-red-950/10 border border-red-900/30">
<div className="text-red-400 font-semibold">Unrecognized Payload</div>
<CodeBlock language="json" value={JSON.stringify(event.payload)} />
</div>
```

**Known unhandled types:**
- `thinking` blocks sent as `{ type: "thinking", thinking: "..." }` (Claude extended thinking format, distinct from `<think>` tags)
- `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.
- Status/progress events from tool execution
- `signature` blocks (`{ type: "signature", ... }`)

---

### 4. Tag Bleed — Internal Routing Tags in User Feed

**Severity:** Medium
**Location:** `normalize-content.ts` `parseTextWithThoughts()`

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.

**Fix required:** A tag-stripping pass before rendering text events. Pattern: `[[...]]` at the start of text content.

---

### 5. Composer Feature Gap Between Pre-Session and In-Session

**Severity:** High
**Location:** `controls-bar.tsx` vs `sessions/page.tsx`

**Pre-session form (`/sessions`)** offers:
- Agent selection dropdown
- Model override (sonnet-4.6, opus-4.6, haiku-4.5, gpt-5.2, gpt-5.3-codex)
- Workflow template (scaffold, pr-review, atomic-commit)
- Skill profile (web-tavily, mcp-local, all)
- File attachments with drag-and-drop
- 4-level thinking selector (Default, Low, Medium, High) — segmented control

**In-session composer (`/sessions/[key]`)** offers:
- Textarea
- "Basic" / "Deep Think" buttons (call `sessions.patch` — different mechanism than send-time params)
- Abort button
- Send button

**Missing from in-session:** Model override, workflow, skills, attachments, granular thinking levels, any visual indication of current model/thinking state.

---

### 6. Additional UX Gaps (Discovered via Code Review)

**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.

**No streaming/loading indicator.** When `sendMutation.isPending`, the Send button says "Sending..." but nothing appears in the transcript until the full response arrives.

**No message timestamps by default.** Timestamps exist but are hidden with `opacity-0 group-hover:opacity-100` — invisible unless hovering.

**No copy/action buttons on messages.** No copy-to-clipboard, no message regeneration, no edit-and-resubmit.

**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.

**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.

**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.

---

## Summary Matrix

| Issue | Severity | Category | Fix Complexity |
|-------|----------|----------|---------------|
| No streaming | Critical | Architecture | High — requires event subscription pipeline |
| Broken metadata | High | Data flow | Medium — query consolidation + title derivation |
| Unhandled payloads | High | Parsing | Low — extend `parseEvents()` |
| Tag bleed | Medium | Parsing | Low — regex strip before render |
| Composer gap | High | Component | Medium — port pre-session controls to in-session |
| Missing scroll button | Medium | UX | Low |
| No loading indicator | High | UX | Low-Medium |
| No message actions | Medium | UX | Medium |
| Minimal markdown | High | Rendering | Medium — integrate react-markdown |
| Non-collapsible panel | Medium | Layout | Low |
Loading