Chat Feature

Real-time AI conversations with streaming responses, context management, session persistence, and tool transparency. The most sophisticated feature in the Parachute app.

49
Files
~17,000
Lines of Code
21
Widgets
16
Models

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.

Performance Optimizations:
  • AutomaticKeepAliveClientMixin - Prevents rebuild during scroll
  • RepaintBoundary - Isolates paint operations
  • LayoutBuilder instead of MediaQuery - 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
    └── ...

Related Documentation