User messages from opencode have no completed_at and normalize to status=in_progress,
which made hasInProgress always true → Stop button stuck on. Filter to assistant-only.
- Sidebar: removed nav items (New Agent, Automations, Dashboard, Bugbot)
- Search placeholder: 'Search sessions ⌘K'
- Composer is sticky at the bottom (outside scroll container) so the thread scrolls cleanly
- Enter sends; Shift+Enter inserts a newline (Cmd+Enter no longer required)
- Optimistic user message renders with a 'queued' spinner badge until the server confirms
- Always poll /v2/sessions every 5s so externally-created sessions appear in the rail without reload
- Always poll /messages (5s when idle, 2s when in_progress) so externally-sent messages appear without reload
- Auto-scroll only triggers when user is already near the bottom (no hijacking)
- Sidebar: hamburger + search input, nav items (New Agent/Automations/Dashboard/Bugbot), session groups (Today/This Week/This Month/Older), active item with blue tinted bg + dot, user footer with avatar
- MainPanel: breadcrumb header agent / repo, max-w-720 thread, user messages as quoted prompt blocks (gray bg rounded-xl), flowing assistant markdown, tool calls as expandable cards with emerald check icon
- Composer: large bordered rounded-xl input, model name on left, dark circular Send (ArrowUp) or Stop (Square) on right
- Inter + JetBrains Mono via Google Fonts
- sessions list as left rail (was full-page list view)
- group sessions by Today/This Week/Last Week/Older
- active row uses subtle bg (was 2px border)
- status dots only render for non-ready states
- header shows agent name from agentNameById fallback
- composer in rounded bordered container with consolidated footer
- stop button is filled-dark SVG square (was bold ascii character)
- markdown sizes tightened (h1 17px, h2 15px, h3 13.5px, body 13.5/1.6)
- user messages render as bold quote-headers with hairline separator
- redirect /sessions to latest session
test_create_agent_same_name_different_user_returns_200 requested monkeypatch
but only used app.dependency_overrides. Pyright flagged the parameter as
unaccessed; remove it.
Use getattr with a None default and isinstance narrowing instead of hasattr to
unwrap prisma.Json-style configs. Pyright was flagging .data access on the
dict branch of the union; this rewrites the path so the type narrows cleanly
without an Any cast.
Verifies agent ownership before listing (404 for unknown/unowned agents).
Sessions are scoped by created_by independent of the agent check, so a
mis-owned session row cannot leak. Optional ?status= filter, same offset
cursor as GET /v2/agents. sandbox_url and sandbox_metadata stripped per
contract \xc2\xa76.2/\xc2\xa76.3.
Both scoped by created_by, ordered by created_at desc, simple offset-based
pagination via take/skip. list_sessions_for_agent supports an optional
SessionStatus filter.
Used by the new GET /v2/agents and GET /v2/agents/:agent_id/sessions
listing endpoints. Each list response carries data + next_cursor + has_more
for simple offset-based pagination.