6.1 KiB
Analytics State Detection System
Overview
This document describes how the Claude Code Analytics Dashboard determines and displays conversation states in real-time.
State Detection Flow
1. Backend State Calculation (/api/conversation-state)
The conversation state endpoint processes ALL conversations and calculates their current state:
API Endpoint: /api/conversation-state
- Method: GET
- Response Format:
{ activeStates: {conversationId: state}, timestamp: number } - Update Frequency: Called by frontend every 5-30 seconds
State Calculation Logic
For each conversation, the system:
-
Checks for Running Process:
- If
conversation.runningProcessexists, usesStateCalculator.quickStateCalculation() - Returns states like: "Claude Code working...", "Awaiting user input...", "User typing..."
- If
-
Falls back to Basic Heuristics (for conversations without active processes):
const timeDiff = (now - new Date(conversation.lastModified)) / (1000 * 60); // minutes if (timeDiff < 5) { state = 'Recently active'; } else if (timeDiff < 60) { state = 'Idle'; } else if (timeDiff < 1440) { // 24 hours state = 'Inactive'; } else { state = 'Old'; }
2. StateCalculator Logic (src/analytics/core/StateCalculator.js)
The StateCalculator determines detailed conversation states based on:
Primary Factors:
- Running Process: Whether there's an active Claude Code process
- Last Message Role: 'user' vs 'assistant'
- Message Timing: Time since last message
- File Activity: File modification time
- Process Activity: Active commands in the process
State Categories:
Active Process States:
"Claude Code working..."- User just sent message or recent file activity"Awaiting user input..."- Claude responded and waiting for user"User typing..."- User hasn't responded for a while"Awaiting response..."- User sent message but Claude hasn't responded
Inactive Process States:
"Recently active"- Modified within 5 minutes"Idle"- Modified within 1 hour"Inactive"- Modified within 24 hours"Old"- Modified more than 24 hours ago
3. Frontend State Display (AgentsPage.js)
State Mapping
The frontend maps backend states to display labels and CSS classes:
// Label mapping
const stateLabels = {
'Claude Code working...': 'Working',
'Awaiting user input...': 'Awaiting input',
'User typing...': 'Typing',
'Awaiting response...': 'Awaiting response',
'Recently active': 'Recent',
'Idle': 'Idle',
'Inactive': 'Inactive',
'Old': 'Old',
'unknown': 'Unknown'
};
// CSS class mapping
const stateClasses = {
'Claude Code working...': 'status-active',
'Awaiting user input...': 'status-waiting',
'User typing...': 'status-typing',
'Awaiting response...': 'status-pending',
'Recently active': 'status-recent',
'Idle': 'status-idle',
'Inactive': 'status-inactive',
'Old': 'status-old',
'unknown': 'status-unknown'
};
Visual Indicators
States are displayed in the conversation sidebar as:
- Status Dot: Colored circle indicator
- Status Badge: Text label with background color
- CSS Classes: For consistent styling across components
Real-time Updates
WebSocket Integration
- State changes are pushed via WebSocket when available
- Falls back to polling every 5-30 seconds when WebSocket unavailable
Update Triggers
- File system changes (FileWatcher)
- Process detection updates
- Periodic refresh intervals
Troubleshooting
Common Issues
-
States showing as "unknown":
- Check if
/api/conversation-stateis returning data - Verify conversation IDs match between API and frontend
- Ensure StateCalculator is processing all conversations
- Check if
-
States not updating in real-time:
- Check WebSocket connection in browser dev tools
- Verify FileWatcher is detecting changes
- Check for polling fallback activation
-
Incorrect state calculations:
- Review StateCalculator logic for edge cases
- Check conversation file modification times
- Verify process detection is working
Debug Commands
# Test state endpoint
curl -s http://localhost:3333/api/conversation-state | jq .
# Check conversations count
curl -s "http://localhost:3333/api/conversations?page=0&limit=1" | jq '.pagination.totalCount'
# Monitor server logs for state calculation
# Look for: "🔍 Processing X conversations for state calculation"
Configuration
State Update Intervals
- With WebSocket: 30 seconds cache duration
- Without WebSocket: 5 seconds cache duration
- File Watch: Immediate updates when files change
Performance Considerations
- StateCalculator uses caching to avoid repeated calculations
- Quick state calculation for active processes only
- Batch processing of all conversations in single API call
Future Improvements
- Enhanced Process Detection: Better correlation between conversations and running processes
- Message-Level Analysis: Analyze message content for more accurate state detection
- User Activity Tracking: Detect actual user typing vs idle time
- Custom State Rules: Allow configuration of state calculation logic
- State History: Track state changes over time for analytics
Integration Points
Files Involved
/src/analytics.js- Main server and API endpoints/src/analytics/core/StateCalculator.js- Core state logic/src/analytics-web/components/AgentsPage.js- Frontend display/src/analytics-web/services/DataService.js- API communication/src/analytics-web/index.html- CSS styling
Key Functions
StateCalculator.determineConversationState()- Main state detectionStateCalculator.quickStateCalculation()- Fast state for active processesAgentsPage.getStateClass()- CSS class mappingAgentsPage.getStateLabel()- Display label mappingDataService.getConversationStates()- API communication
This system provides real-time visibility into Claude Code conversation states, helping users understand what's happening across all their active sessions.