Decomposed "Foundation Setup - Install Dependencies & Configure Tailwind" phase into 6 executable tasks: 1. Install Tailwind CSS, PostCSS & Autoprefixer 2. Map MUI theme to Tailwind design tokens 3. Setup CSS variables for dynamic theming 4. Install Radix UI primitives 5. Initialize shadcn/ui and setup component directory 6. Move MUI to devDependencies and verify setup Tasks follow logical dependency chain with final human verification checkpoint before proceeding with component migration. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
365 lines
17 KiB
Markdown
365 lines
17 KiB
Markdown
# Agent Inbox Wireframe
|
|
|
|
Message queue UI where users see questions from agents and respond to them.
|
|
|
|
## Screen Layout
|
|
|
|
### Inbox List View
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Agent Inbox (3) [Refresh] │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Filter: [All ▾] Sort: [Newest ▾] │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ ● gastown (waiting) 2 min ago │
|
|
│ "Which auth provider should we use? I need to decide..." │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ ● chinatown (waiting) 5 min ago │
|
|
│ "I found 3 potential issues with the migration..." │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ ○ yaletown (done) 15 min ago │
|
|
│ "Task completed: Created user schema" │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Legend:**
|
|
- ● = Requires response (agent waiting)
|
|
- ○ = Informational (no response needed)
|
|
|
|
### Empty State
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Agent Inbox (0) [Refresh] │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ No pending messages │
|
|
│ │
|
|
│ Agents will appear here when they have │
|
|
│ questions or status updates │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Message Detail View
|
|
|
|
### Single Question (Radio Buttons)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ gastown → You 2 minutes ago │
|
|
│ Task: Implement auth middleware │
|
|
│ Worktree: .cw-worktrees/gastown │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Q1: Which authentication provider should we use? │
|
|
│ │
|
|
│ ○ Supabase Auth - Built-in with our DB │
|
|
│ ○ Clerk - Beautiful pre-built UI │
|
|
│ ○ NextAuth.js - Self-hosted, maximum control │
|
|
│ ○ Other: [________________] │
|
|
│ │
|
|
│ [Cancel] [Send Answers] │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Multi-Question Format
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ gastown → You 2 minutes ago │
|
|
│ Task: Implement auth middleware │
|
|
│ Worktree: .cw-worktrees/gastown │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Q1: Which authentication provider should we use? │
|
|
│ │
|
|
│ ○ Supabase Auth - Built-in with our DB │
|
|
│ ○ Clerk - Beautiful pre-built UI │
|
|
│ ○ NextAuth.js - Self-hosted, maximum control │
|
|
│ ○ Other: [________________] │
|
|
│ │
|
|
│ Q2: Should we implement refresh token rotation? │
|
|
│ │
|
|
│ ○ Yes - More secure │
|
|
│ ○ No - Simpler implementation │
|
|
│ │
|
|
│ Q3: Session storage preference? │
|
|
│ │
|
|
│ ○ Database - Full control, revocation │
|
|
│ ○ JWT only - Stateless, simpler │
|
|
│ │
|
|
│ [Cancel] [Send Answers] │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Multi-Select Question (Checkboxes)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ chinatown → You 5 minutes ago │
|
|
│ Task: Configure database schema │
|
|
│ Worktree: .cw-worktrees/chinatown │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Q1: Which optional features should we include? │
|
|
│ (Select all that apply) │
|
|
│ │
|
|
│ ☐ Soft deletes - Mark deleted instead of removing │
|
|
│ ☐ Audit logging - Track all changes │
|
|
│ ☐ Full-text search - PostgreSQL tsvector │
|
|
│ ☐ Row-level security - Fine-grained access │
|
|
│ │
|
|
│ Q2: Primary key strategy? │
|
|
│ │
|
|
│ ○ UUID - Globally unique, no collisions │
|
|
│ ○ Serial - Simple, human-readable │
|
|
│ ○ ULID - Sortable UUIDs │
|
|
│ │
|
|
│ [Cancel] [Send Answers] │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Free-Text Answer
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ yaletown → You 10 minutes ago │
|
|
│ Task: Set up deployment │
|
|
│ Worktree: .cw-worktrees/yaletown │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ Q1: What should the production domain be? │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ app.example.com │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Q2: Any custom environment variables needed? │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────┐ │
|
|
│ │ FEATURE_FLAGS=beta │ │
|
|
│ │ API_RATE_LIMIT=1000 │ │
|
|
│ └─────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ [Cancel] [Send Answers] │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### Notification Message (No Response)
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ yaletown → You 15 minutes ago │
|
|
│ Task: Create user schema │
|
|
│ Worktree: .cw-worktrees/yaletown │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ✓ Task completed successfully │
|
|
│ │
|
|
│ Created: │
|
|
│ - src/db/schema/user.ts │
|
|
│ - src/db/schema/session.ts │
|
|
│ - migrations/001_create_users.sql │
|
|
│ │
|
|
│ Ready for merge into main branch. │
|
|
│ │
|
|
│ [Dismiss] [View Changes] │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Component Specifications
|
|
|
|
### InboxList
|
|
|
|
**Props:**
|
|
- `messages: Message[]` - List of messages to display
|
|
- `filter: 'all' | 'waiting' | 'completed'` - Current filter state
|
|
- `sort: 'newest' | 'oldest'` - Sort order
|
|
- `onFilterChange: (filter) => void` - Filter change handler
|
|
- `onSortChange: (sort) => void` - Sort change handler
|
|
- `onRefresh: () => void` - Refresh handler
|
|
- `onSelectMessage: (messageId: string) => void` - Message selection handler
|
|
|
|
**Behavior:**
|
|
- Displays message cards in a scrollable list
|
|
- Shows unread count badge in header
|
|
- Filterable by status (All, Waiting, Completed)
|
|
- Sortable by timestamp (Newest first, Oldest first)
|
|
- Clicking a message expands the detail view
|
|
|
|
### MessageCard
|
|
|
|
**Props:**
|
|
- `message: Message` - Message data
|
|
- `isSelected: boolean` - Whether this card is currently selected
|
|
- `onClick: () => void` - Click handler
|
|
|
|
**Display:**
|
|
- Sender agent name with status indicator (● waiting, ○ done)
|
|
- Message preview (first line, truncated)
|
|
- Relative timestamp (e.g., "2 min ago", "1 hour ago")
|
|
|
|
**States:**
|
|
- Default - normal styling
|
|
- Selected - highlighted/expanded
|
|
- Unread - bold text, filled indicator
|
|
|
|
### MessageDetail
|
|
|
|
**Props:**
|
|
- `message: Message` - Full message data
|
|
- `onSubmit: (answers: Record<string, string>) => void` - Submit handler
|
|
- `onCancel: () => void` - Cancel/close handler
|
|
|
|
**Display:**
|
|
- Header: Sender name, timestamp, task info, worktree path
|
|
- Content: All questions with their input components
|
|
- Footer: Action buttons (Cancel, Send Answers / Dismiss)
|
|
|
|
**Behavior:**
|
|
- Validates all required questions are answered before enabling submit
|
|
- Calls agent resume with formatted answers on submit
|
|
- Closes detail view on cancel or successful submit
|
|
|
|
### QuestionForm
|
|
|
|
**Props:**
|
|
- `questions: Question[]` - Array of questions to render
|
|
- `answers: Record<string, string>` - Current answer state
|
|
- `onAnswerChange: (questionId: string, answer: string) => void` - Answer change handler
|
|
|
|
**Renders:**
|
|
- Sequential question components based on question type
|
|
- Each question has unique ID for answer correlation
|
|
- Supports mixed question types in same form
|
|
|
|
### OptionGroup
|
|
|
|
**Props:**
|
|
- `questionId: string` - Question identifier
|
|
- `options: Option[]` - Available options
|
|
- `multiSelect: boolean` - Whether to use checkboxes (true) or radio buttons (false)
|
|
- `value: string | string[]` - Current selection
|
|
- `onChange: (value: string | string[]) => void` - Change handler
|
|
- `allowOther: boolean` - Whether to show "Other" free-text option
|
|
|
|
**Behavior:**
|
|
- Radio buttons for single-select (default)
|
|
- Checkboxes for multi-select
|
|
- "Other" field appears when `allowOther` is true
|
|
- Typing in "Other" selects it automatically
|
|
|
|
### FreeTextInput
|
|
|
|
**Props:**
|
|
- `questionId: string` - Question identifier
|
|
- `placeholder: string` - Placeholder text
|
|
- `multiline: boolean` - Single line or textarea
|
|
- `value: string` - Current value
|
|
- `onChange: (value: string) => void` - Change handler
|
|
|
|
**Behavior:**
|
|
- Single line input for short answers
|
|
- Textarea for longer content (auto-resize optional)
|
|
- Character limit indicator if applicable
|
|
|
|
## Interaction Notes
|
|
|
|
### Message Selection Flow
|
|
|
|
1. User clicks message in InboxList
|
|
2. MessageCard enters selected state
|
|
3. MessageDetail panel appears (expands below or in side panel)
|
|
4. Previous selection collapses
|
|
|
|
### Answer Submission Flow
|
|
|
|
1. User selects/enters answers for all questions
|
|
2. "Send Answers" button becomes enabled when all required answered
|
|
3. User clicks "Send Answers"
|
|
4. System calls `agent.resume` with formatted answers:
|
|
```typescript
|
|
{
|
|
[questionId: string]: answer: string
|
|
}
|
|
```
|
|
5. Detail panel closes
|
|
6. Message moves to "Completed" status
|
|
7. Agent continues execution
|
|
|
|
### Notification Handling
|
|
|
|
1. Completed task notifications don't require response
|
|
2. User can dismiss to archive
|
|
3. "View Changes" opens diff/preview (future feature)
|
|
|
|
### Real-Time Updates
|
|
|
|
1. New messages appear at top with subtle animation
|
|
2. Unread count updates automatically
|
|
3. Message status updates when agent state changes
|
|
4. Optional desktop notification for new messages
|
|
|
|
## Filter & Sort Options
|
|
|
|
### Filter Options
|
|
|
|
| Filter | Shows |
|
|
|--------|-------|
|
|
| All | All messages |
|
|
| Waiting | Messages requiring response (agent status = waiting_for_input) |
|
|
| Completed | Notifications and answered messages |
|
|
|
|
### Sort Options
|
|
|
|
| Sort | Behavior |
|
|
|------|----------|
|
|
| Newest first | Most recent at top (default) |
|
|
| Oldest first | Oldest at top |
|
|
|
|
## Data Schema Reference
|
|
|
|
### Message
|
|
|
|
```typescript
|
|
interface Message {
|
|
id: string
|
|
sender: { type: 'agent' | 'user', id?: string }
|
|
recipient: { type: 'agent' | 'user', id?: string }
|
|
content: string
|
|
requiresResponse: boolean
|
|
parentMessageId?: string // For response threading
|
|
createdAt: Date
|
|
}
|
|
```
|
|
|
|
### Question
|
|
|
|
```typescript
|
|
interface Question {
|
|
id: string // Unique ID for answer correlation
|
|
question: string // The question text
|
|
options?: Option[] // Available choices
|
|
multiSelect?: boolean // Checkboxes vs radio buttons
|
|
}
|
|
|
|
interface Option {
|
|
value: string
|
|
label: string
|
|
}
|
|
```
|
|
|
|
### Agent Context
|
|
|
|
```typescript
|
|
interface AgentContext {
|
|
name: string // Human-readable name (gastown, chinatown)
|
|
status: AgentStatus // 'waiting_for_input' | 'running' | 'completed'
|
|
taskId?: string // Associated task
|
|
worktreeId?: string // Associated worktree
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
*Wireframe: Agent Inbox*
|
|
*Created: 2026-02-02*
|