(success: boolean)
| 630 | |
| 631 | // Helper to handle completion events (both generic and scoped) |
| 632 | const processComplete = async (success: boolean) => { |
| 633 | setIsLoading(false); |
| 634 | hasActiveSessionRef.current = false; |
| 635 | isListeningRef.current = false; // Reset listening state |
| 636 | |
| 637 | // Track enhanced session stopped metrics when session completes |
| 638 | if (effectiveSession && claudeSessionId) { |
| 639 | const sessionStartTimeValue = messages.length > 0 ? messages[0].timestamp || Date.now() : Date.now(); |
| 640 | const duration = Date.now() - sessionStartTimeValue; |
| 641 | const metrics = sessionMetrics.current; |
| 642 | const timeToFirstMessage = metrics.firstMessageTime |
| 643 | ? metrics.firstMessageTime - sessionStartTime.current |
| 644 | : undefined; |
| 645 | const idleTime = Date.now() - metrics.lastActivityTime; |
| 646 | const avgResponseTime = metrics.toolExecutionTimes.length > 0 |
| 647 | ? metrics.toolExecutionTimes.reduce((a, b) => a + b, 0) / metrics.toolExecutionTimes.length |
| 648 | : undefined; |
| 649 | |
| 650 | trackEvent.enhancedSessionStopped({ |
| 651 | // Basic metrics |
| 652 | duration_ms: duration, |
| 653 | messages_count: messages.length, |
| 654 | reason: success ? 'completed' : 'error', |
| 655 | |
| 656 | // Timing metrics |
| 657 | time_to_first_message_ms: timeToFirstMessage, |
| 658 | average_response_time_ms: avgResponseTime, |
| 659 | idle_time_ms: idleTime, |
| 660 | |
| 661 | // Interaction metrics |
| 662 | prompts_sent: metrics.promptsSent, |
| 663 | tools_executed: metrics.toolsExecuted, |
| 664 | tools_failed: metrics.toolsFailed, |
| 665 | files_created: metrics.filesCreated, |
| 666 | files_modified: metrics.filesModified, |
| 667 | files_deleted: metrics.filesDeleted, |
| 668 | |
| 669 | // Content metrics |
| 670 | total_tokens_used: totalTokens, |
| 671 | code_blocks_generated: metrics.codeBlocksGenerated, |
| 672 | errors_encountered: metrics.errorsEncountered, |
| 673 | |
| 674 | // Session context |
| 675 | model: metrics.modelChanges.length > 0 |
| 676 | ? metrics.modelChanges[metrics.modelChanges.length - 1].to |
| 677 | : 'sonnet', |
| 678 | has_checkpoints: metrics.checkpointCount > 0, |
| 679 | checkpoint_count: metrics.checkpointCount, |
| 680 | was_resumed: metrics.wasResumed, |
| 681 | |
| 682 | // Agent context (if applicable) |
| 683 | agent_type: undefined, // TODO: Pass from agent execution |
| 684 | agent_name: undefined, // TODO: Pass from agent execution |
| 685 | agent_success: success, |
| 686 | |
| 687 | // Stop context |
| 688 | stop_source: 'completed', |
| 689 | final_state: success ? 'success' : 'failed', |
no test coverage detected