Chat Feature
Real-time AI conversations with streaming responses, context management, session persistence, and tool transparency. The most sophisticated feature in the Parachute app.
Architecture Overview
┌─────────────────────────────────────────────────────────────────────────┐ │ CHAT FEATURE │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Models │ │ Services │ │ Providers │ │ │ │ (16 files) │ │ (6 files) │ │ (1 file) │ │ │ │ │ │ │ │ │ │ │ │ ChatSession │ │ ChatService │ │ chatSessions │ │ │ │ ChatMessage │ │ BackgroundMgr │ │ chatMessages │ │ │ │ StreamEvent │ │ LocalReader │ │ contextFiles │ │ │ │ SessionTranscript│ │ ImportService │ │ usageProvider │ │ │ │ SystemPromptInfo│ │ ParaIdService │ │ currentSession │ │ │ │ ... │ │ │ │ │ │ │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ │ │ │ │ │ │ └──────────────────────┼──────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ SCREENS │ │ │ │ │ │ │ │ ChatScreen → MessageBubbles + ChatInput + ConnectionBanner │ │ │ │ ChatHubScreen → Session list with search/filter │ │ │ │ AgentHubScreen → Agent selection │ │ │ │ ClaudeCodeImportScreen → Session import workflow │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ WIDGETS (21) │ │ │ │ │ │ │ │ MessageBubble (1,570 lines) - Markdown rendering, tool calls │ │ │ │ ChatInput (1,076 lines) - Text input, attachments, agents │ │ │ │ SessionSelector - Bottom sheet for session switching │ │ │ │ CollapsibleThinkingSection - Tool call display │ │ │ │ UserQuestionCard - AskUserQuestion tool UI │ │ │ │ ErrorRecoveryCard - Typed error with recovery actions │ │ │ │ ... │ │ │ └─────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘
Streaming Data Flow
User Input → ChatInput → chatMessagesProvider → ChatService.streamChat()
│
POST /api/chat
│
Server-Sent Events (SSE)
│
StreamEvent parser
│
ChatMessagesNotifier
│
┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
TextEvent ToolUseEvent ThinkingEvent
│ │ │
└───────────────────────────┼───────────────────────────┘
│
MessageBubble (UI)
Stream Event Types
The StreamEventType enum defines 23 event types for comprehensive state tracking:
| Category | Events | Purpose |
|---|---|---|
| Session | session, init, model, done |
Session lifecycle tracking |
| Messages | userMessage, text, thinking |
Content streaming |
| Tools | toolUse, toolResult |
Tool execution transparency |
| Special | userQuestion, promptMetadata |
Interactive and transparency features |
| Errors | sessionUnavailable, aborted, error, typedError |
Error handling and recovery |
Core Models
ChatSession
Primary session model with metadata and state tracking.
class ChatSession {
final String id; // SDK session ID (single ID for all operations)
final String? title; // Auto-generated or user-set
final String module; // 'chat', 'daily', 'build'
final String source; // 'parachute', 'claude-code', 'claude', 'chatgpt'
final String? workingDirectory; // For file operations
final String? model; // e.g., 'claude-opus-4'
final int messageCount; // Total messages
final bool archived; // Soft delete flag
final DateTime createdAt;
final DateTime lastAccessed;
final String? continuedFrom; // Parent session ID
final String? agentType; // 'vault-agent', 'orchestrator', etc.
}
ChatMessage
Represents individual messages with rich content blocks.
class ChatMessage {
final String? paraId; // Cross-device sync ID: para:abc123def456
final String id; // Local ID (may be UUID during streaming)
final ChatRole role; // user, assistant, system
final List<ContentBlock> content; // Text, thinking, tool_use, tool_result
final DateTime? timestamp;
final bool isStreaming; // Currently being received
final bool isCompactSummary; // Auto-generated summary (collapsed)
final List<ChatAttachment>? attachments;
}
ContentBlock Types
| Type | Description | UI Treatment |
|---|---|---|
text |
Regular markdown content | Full markdown rendering |
thinking |
Internal reasoning | Collapsible section |
tool_use |
Tool invocation | Collapsible with input/output |
tool_result |
Tool response | Nested in tool_use |
Session Resumption Strategy
Three methods for resuming sessions, applied in order of preference:
1. SDK Resume
Fastest: Native Claude SDK session resumption. SDK maintains full context internally.
- Used when SDK session file exists
- Full tool history preserved
- No token overhead
2. Context Injection
Fallback: Re-send prior messages as system context when SDK session unavailable.
- Used for imported sessions
- Token-limited injection
- Tool results not included
3. New Session
Fresh Start: No prior context loaded. Used when explicitly creating new conversation.
- Clean slate
- May reference
continuedFrom - Fastest startup
Resume info is tracked via SessionResumeInfo and displayed in the UI with SessionResumeBanner.
Context System
Context Chain
CLAUDE.md files are loaded from the working directory upward to the vault root:
~/Parachute/ ← Root CLAUDE.md (if exists)
└── Projects/
└── myapp/ ← Parent CLAUDE.md
└── src/ ← Direct CLAUDE.md (working directory)
└── components/
Context chain loads: root → parent → direct
With token counting and truncation warning
Context Types
| Type | Location | Purpose |
|---|---|---|
| Context Files | Chat/contexts/*.md |
Stored context documents for reference |
| Context Folders | Any folder with CLAUDE.md |
Project-specific instructions |
| Context Chain | Working directory hierarchy | Inherited context with token limits |
ChatService (2,060 lines)
The main HTTP client for Computer server communication.
Key Methods
| Method | Endpoint | Purpose |
|---|---|---|
streamChat() |
POST /api/chat |
Primary streaming method - yields StreamEvent stream |
getSessions() |
GET /api/chat |
Fetch all sessions (limits to 500) |
getSession() |
GET /api/chat/:id |
Fetch specific session with messages |
abortStream() |
POST /api/chat/abort |
Cancel ongoing stream |
answerQuestion() |
POST /api/chat/answer |
Respond to AskUserQuestion tool |
Streaming Configuration
- Connection timeout: 30 seconds
- Chunk timeout: 3 minutes (detects stalled connections)
- SSE Format:
data: {...json...}\n\n - UTF-8 Decoding: Handles multi-byte characters across chunks
Key Widgets
MessageBubble (1,570 lines)
The most complex widget - renders individual chat messages with full markdown support.
AutomaticKeepAliveClientMixin- Prevents rebuild during scrollRepaintBoundary- Isolates paint operationsLayoutBuilderinstead ofMediaQuery- Prevents unnecessary rebuilds
Supported Markdown Features
- Headings (h1-h6) with proper sizing
- Code blocks with syntax highlighting
- Tables with borders and padding
- Blockquotes with left border styling
- Links with vault file support
- Embedded audio player for audio files
ChatInput (1,076 lines)
Text input with attachment management and agent selection.
- Expandable text field (grows with content)
- Multi-file attachment picker
- Agent selector dropdown
- Context folder selector
- Keyboard shortcuts (Cmd+Enter to send)
CollapsibleThinkingSection (774 lines)
Groups and displays thinking blocks and tool calls.
- Collapsed by default during playback
- Expanded during active streaming
- Tool result error highlighting
Post-Session Processing
After each chat exchange, a post-session hook handles background maintenance:
Chat Session Complete
│
├── Activity Hook triggers
│
▼
Post-Session Tasks
│
├── Update session title (first message)
├── Summarize exchange to Daily/chat-log/
└── Track usage metrics
Background Tasks
- Title Generation: Auto-generates descriptive titles from first exchange
- Chat Logging: Summarizes exchange to
Daily/chat-log/{date}.md - Metrics: Tracks token usage and session statistics
Error Handling
TypedError System
Structured errors with programmatic recovery suggestions:
| ErrorCode | Description | Recovery Actions |
|---|---|---|
auth_error |
API key invalid | Settings, Reauth |
billing_error |
Usage limits exceeded | Dismiss, Settings |
rate_limit |
Too many requests | Retry (with delay) |
network_error |
Connection failed | Retry |
session_error |
Session unavailable | New Session |
Each RecoveryAction includes a keyboard shortcut hint for power users.
File Structure
app/lib/features/chat/
├── models/ # 16 files, ~2,200 lines
│ ├── chat_session.dart
│ ├── chat_message.dart
│ ├── stream_event.dart
│ ├── session_transcript.dart
│ ├── system_prompt_info.dart
│ ├── context_file.dart
│ ├── context_folder.dart
│ ├── agent.dart
│ ├── attachment.dart
│ ├── claude_usage.dart
│ ├── session_resume_info.dart
│ ├── prompt_metadata.dart
│ └── typed_error.dart
├── providers/ # 1 file, ~2,800 lines
│ └── chat_providers.dart
├── services/ # 6 files, ~2,200 lines
│ ├── chat_service.dart
│ ├── background_stream_manager.dart
│ ├── local_session_reader.dart
│ ├── chat_import_service.dart
│ └── para_id_service.dart
├── screens/ # 5 files, ~600 lines
│ ├── chat_screen.dart
│ ├── chat_hub_screen.dart
│ ├── agent_hub_screen.dart
│ └── claude_code_import_screen.dart
└── widgets/ # 21 files, ~9,200 lines
├── message_bubble.dart
├── chat_input.dart
├── session_selector.dart
├── collapsible_thinking_section.dart
├── user_question_card.dart
├── error_recovery_card.dart
└── ...