(log: LogOption)
| 735 | } |
| 736 | |
| 737 | function logToSessionMeta(log: LogOption): SessionMeta { |
| 738 | const stats = extractToolStats(log) |
| 739 | const sessionId = getSessionIdFromLog(log) || 'unknown' |
| 740 | const startTime = log.created.toISOString() |
| 741 | const durationMinutes = Math.round( |
| 742 | (log.modified.getTime() - log.created.getTime()) / 1000 / 60, |
| 743 | ) |
| 744 | |
| 745 | let userMessageCount = 0 |
| 746 | let assistantMessageCount = 0 |
| 747 | for (const msg of log.messages) { |
| 748 | if (msg.type === 'assistant') assistantMessageCount++ |
| 749 | // Only count user messages that have actual text content (human messages) |
| 750 | // not just tool_result messages (matching Python reference) |
| 751 | if (msg.type === 'user' && msg.message) { |
| 752 | const content = msg.message.content |
| 753 | let isHumanMessage = false |
| 754 | if (typeof content === 'string' && content.trim()) { |
| 755 | isHumanMessage = true |
| 756 | } else if (Array.isArray(content)) { |
| 757 | for (const block of content) { |
| 758 | if (block.type === 'text' && 'text' in block) { |
| 759 | isHumanMessage = true |
| 760 | break |
| 761 | } |
| 762 | } |
| 763 | } |
| 764 | if (isHumanMessage) { |
| 765 | userMessageCount++ |
| 766 | } |
| 767 | } |
| 768 | } |
| 769 | |
| 770 | return { |
| 771 | session_id: sessionId, |
| 772 | project_path: log.projectPath || '', |
| 773 | start_time: startTime, |
| 774 | duration_minutes: durationMinutes, |
| 775 | user_message_count: userMessageCount, |
| 776 | assistant_message_count: assistantMessageCount, |
| 777 | tool_counts: stats.toolCounts, |
| 778 | languages: stats.languages, |
| 779 | git_commits: stats.gitCommits, |
| 780 | git_pushes: stats.gitPushes, |
| 781 | input_tokens: stats.inputTokens, |
| 782 | output_tokens: stats.outputTokens, |
| 783 | first_prompt: log.firstPrompt || '', |
| 784 | summary: log.summary, |
| 785 | // New stats |
| 786 | user_interruptions: stats.userInterruptions, |
| 787 | user_response_times: stats.userResponseTimes, |
| 788 | tool_errors: stats.toolErrors, |
| 789 | tool_error_categories: stats.toolErrorCategories, |
| 790 | uses_task_agent: stats.usesTaskAgent, |
| 791 | uses_mcp: stats.usesMcp, |
| 792 | uses_web_search: stats.usesWebSearch, |
| 793 | uses_web_fetch: stats.usesWebFetch, |
| 794 | // Additional stats |
no test coverage detected