claude-code-tracker/recalculate_project_stats.py
Ryan Malloy bec1606c86 Add comprehensive documentation system and tool call tracking
## Documentation System
- Create complete documentation hub at /dashboard/docs with:
  - Getting Started guide with quick setup and troubleshooting
  - Hook Setup Guide with platform-specific configurations
  - API Reference with all endpoints and examples
  - FAQ with searchable questions and categories
- Add responsive design with interactive features
- Update navigation in base template

## Tool Call Tracking
- Add ToolCall model for tracking Claude Code tool usage
- Create /api/tool-calls endpoints for recording and analytics
- Add tool_call hook type with auto-session detection
- Include tool calls in project statistics and recalculation
- Track tool names, parameters, execution time, and success rates

## Project Enhancements
- Add project timeline and statistics pages (fix 404 errors)
- Create recalculation script for fixing zero statistics
- Update project stats to include tool call counts
- Enhance session model with tool call relationships

## Infrastructure
- Switch from requirements.txt to pyproject.toml/uv.lock
- Add data import functionality for claude.json files
- Update database connection to include all new models
- Add comprehensive API documentation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 05:58:27 -06:00

109 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""
Script to recalculate project statistics from imported sessions and conversations.
Run this after importing data to fix zero statistics on the projects page.
"""
import asyncio
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from app.database.connection import engine, async_session_maker
from app.models.project import Project
from app.models.session import Session
from app.models.conversation import Conversation
from app.models.activity import Activity
from app.models.tool_call import ToolCall
async def recalculate_project_stats():
"""Recalculate statistics for all projects based on imported data."""
async with async_session_maker() as db:
try:
# Get all projects
result = await db.execute(select(Project))
projects = result.scalars().all()
print(f"Found {len(projects)} projects to recalculate")
for project in projects:
print(f"\nRecalculating stats for project: {project.name}")
# Get all sessions for this project
session_result = await db.execute(
select(Session).where(Session.project_id == project.id)
)
sessions = session_result.scalars().all()
session_ids = [s.id for s in sessions] if sessions else []
# Calculate session-based statistics
total_sessions = len(sessions)
total_time_minutes = sum(
s.calculated_duration_minutes or 0 for s in sessions
)
# Find last session time
last_session_time = None
if sessions:
last_session_time = max(s.start_time for s in sessions)
# Calculate activity-based statistics
files_modified_count = 0
lines_changed_count = 0
tool_calls_count = 0
if session_ids:
activity_result = await db.execute(
select(Activity).where(Activity.session_id.in_(session_ids))
)
activities = activity_result.scalars().all()
# Count unique files modified
unique_files = set()
total_lines_changed = 0
for activity in activities:
if activity.file_path:
unique_files.add(activity.file_path)
if activity.total_lines_changed:
total_lines_changed += activity.total_lines_changed
files_modified_count = len(unique_files)
lines_changed_count = total_lines_changed
# Count tool calls
session_ids_str = [str(sid) for sid in session_ids]
tool_calls_result = await db.execute(
select(ToolCall).where(ToolCall.session_id.in_(session_ids_str))
)
tool_calls = tool_calls_result.scalars().all()
tool_calls_count = len(tool_calls)
# Update project statistics
project.total_sessions = total_sessions
project.total_time_minutes = total_time_minutes
project.files_modified_count = files_modified_count
project.lines_changed_count = lines_changed_count
project.tool_calls_count = tool_calls_count
if last_session_time:
project.last_session = last_session_time
print(f" Sessions: {total_sessions}")
print(f" Time: {total_time_minutes} minutes")
print(f" Files: {files_modified_count}")
print(f" Lines: {lines_changed_count}")
print(f" Tool calls: {tool_calls_count}")
print(f" Last session: {last_session_time}")
# Commit all changes
await db.commit()
print(f"\nSuccessfully recalculated statistics for {len(projects)} projects")
except Exception as e:
await db.rollback()
print(f"Error recalculating project stats: {e}")
raise
finally:
await engine.dispose()
if __name__ == "__main__":
asyncio.run(recalculate_project_stats())