Skip to content

Frontend: /sessions/[id] detail page — wires SplitPane, AgentChatPanel, and AgentTerminal #509

@frankbria

Description

@frankbria

Parent Issue

Part of #500 — depends on #504, #505, #506, #507, #508

Context

This is the final integration page that assembles all the session UI components into a working interactive session view. It's the most important page from a user-experience perspective — it's where the bidirectional chat actually happens.

What to Build

New page: web-ui/src/app/sessions/[id]/page.tsx

Full-page layout:

┌─ Header ─────────────────────────────────────────────────────────┐
│  ← Sessions    Session #a3f2    🟢 active    $0.012    [End]     │
├─ SplitPane (fills remaining viewport height) ────────────────────┤
│                          │                                        │
│  AgentChatPanel          │  AgentTerminal                        │
│  (45% default)           │  (55% default)                        │
│                          │                                        │
└──────────────────────────────────────────────────────────────────┘

Header:

  • Back link "← Sessions" → /sessions
  • Session short ID
  • State badge (🟢 active / ⚪ ended)
  • Live cost counter (updates from useAgentChat state)
  • [End Session] button — calls DELETE /api/v2/sessions/{id}, confirms, redirects to /sessions on success
  • Disabled [End Session] if already ended

SplitPane:

  • Left: <AgentChatPanel sessionId={id} />
  • Right: <AgentTerminal sessionId={id} />
  • storageKey="session-split-{id}" so position is per-session

Ended session state:

  • If session state is ended: show AgentChatPanel in read-only mode (no input bar) and a banner: "This session has ended. [View history]"
  • AgentTerminal is hidden for ended sessions (or shows "Terminal unavailable — session has ended")
  • Load message history from GET /api/v2/sessions/{id}/messages (REST, not WS) for ended sessions

Loading state:

  • Skeleton: header placeholder + two side-by-side gray boxes filling the viewport

Error state:

  • Session not found: "Session not found" with link back to /sessions
  • WebSocket error: visible error banner inside AgentChatPanel

Data flow:

  1. On mount: GET /api/v2/sessions/{id} to get session metadata (state, model, workspace_path)
  2. If active: mount AgentChatPanel + AgentTerminal (both connect via WS)
  3. If ended: mount read-only AgentChatPanel with history from REST, no terminal

Page title:

  • <title>Session #{shortId} — CodeFRAME</title> via next/head or metadata

Acceptance Criteria

  • Page loads session metadata and renders correct state (active vs ended)
  • AgentChatPanel is mounted and chat is functional for active sessions
  • AgentTerminal is mounted and terminal is functional for active sessions
  • SplitPane divider is draggable; position persists per session
  • [End Session] ends the session and redirects to list
  • Ended sessions show read-only message history, no input bar, no terminal
  • "Session not found" error state displayed correctly
  • Page title includes session short ID
  • Navigating back to /sessions shows updated session state

Notes

  • This is a pure composition page — minimal logic beyond routing and passing sessionId to child components
  • Viewport height: use calc(100vh - headerHeight) for the SplitPane so it fills the screen without scrolling
  • Do not re-fetch session messages in both this page and AgentChatPanel — let the chat panel own its message state via useAgentChat

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions