## 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>
109 lines
4.6 KiB
Python
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()) |