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>
This commit is contained in:
parent
166247bf70
commit
bec1606c86
27 changed files with 6150 additions and 32 deletions
154
import_claude_data.py
Normal file
154
import_claude_data.py
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Command-line tool to import data from .claude.json file.
|
||||
|
||||
Usage:
|
||||
python import_claude_data.py [--file path/to/.claude.json] [--preview]
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from app.database.connection import async_session_maker, init_database
|
||||
from app.api.importer import ClaudeJsonImporter
|
||||
|
||||
|
||||
async def preview_import(file_path: str):
|
||||
"""Preview what would be imported."""
|
||||
print(f"🔍 Previewing import from: {file_path}")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
import json
|
||||
import os
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
print(f"❌ File not found: {file_path}")
|
||||
return False
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
claude_data = json.load(f)
|
||||
|
||||
file_size_mb = round(os.path.getsize(file_path) / (1024 * 1024), 2)
|
||||
|
||||
print(f"📁 File size: {file_size_mb} MB")
|
||||
print(f"🚀 Total Claude Code startups: {claude_data.get('numStartups', 0)}")
|
||||
print(f"📅 First start time: {claude_data.get('firstStartTime', 'N/A')}")
|
||||
print(f"📊 Prompt queue uses: {claude_data.get('promptQueueUseCount', 0)}")
|
||||
|
||||
if "projects" in claude_data:
|
||||
projects = claude_data["projects"]
|
||||
print(f"📂 Projects found: {len(projects)}")
|
||||
|
||||
# Show first few project paths
|
||||
paths = list(projects.keys())[:5]
|
||||
for path in paths:
|
||||
history_count = len(projects[path].get("history", []))
|
||||
print(f" • {path} ({history_count} history entries)")
|
||||
|
||||
if len(projects) > 5:
|
||||
print(f" ... and {len(projects) - 5} more projects")
|
||||
|
||||
# Count total history entries
|
||||
total_history = sum(len(proj.get("history", [])) for proj in projects.values())
|
||||
print(f"💬 Total conversation history entries: {total_history}")
|
||||
|
||||
print("\n✅ Preview completed successfully!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Preview failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
async def run_import(file_path: str):
|
||||
"""Run the actual import process."""
|
||||
print(f"📥 Starting import from: {file_path}")
|
||||
print("=" * 50)
|
||||
|
||||
# Initialize database tables first
|
||||
print("🔧 Initializing database...")
|
||||
await init_database()
|
||||
print("✅ Database initialized")
|
||||
|
||||
async with async_session_maker() as db:
|
||||
try:
|
||||
importer = ClaudeJsonImporter(db)
|
||||
results = await importer.import_from_file(file_path)
|
||||
|
||||
print("🎉 Import completed successfully!")
|
||||
print(f"📂 Projects imported: {results['projects_imported']}")
|
||||
print(f"⏱️ Sessions estimated: {results['sessions_estimated']}")
|
||||
print(f"💬 Conversations imported: {results['conversations_imported']}")
|
||||
|
||||
if results['errors']:
|
||||
print(f"\n⚠️ Warnings/Errors ({len(results['errors'])}):")
|
||||
for error in results['errors']:
|
||||
print(f" • {error}")
|
||||
|
||||
print("\n🚀 You can now view your imported data at: http://localhost:8000")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Import failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Import Claude Code data from .claude.json file",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
python import_claude_data.py --preview
|
||||
python import_claude_data.py --file ~/.claude.json
|
||||
python import_claude_data.py --file ~/.claude.json --preview
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--file",
|
||||
type=str,
|
||||
default=None,
|
||||
help="Path to .claude.json file (default: ~/.claude.json)"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--preview",
|
||||
action="store_true",
|
||||
help="Preview what would be imported without actually importing"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Determine file path
|
||||
if args.file:
|
||||
file_path = args.file
|
||||
else:
|
||||
file_path = str(Path.home() / ".claude.json")
|
||||
|
||||
print("🤖 Claude Code Project Tracker - Data Importer")
|
||||
print("=" * 50)
|
||||
|
||||
if args.preview:
|
||||
success = asyncio.run(preview_import(file_path))
|
||||
else:
|
||||
print("⚠️ This will import data into your Claude Code Project Tracker database.")
|
||||
print(" Make sure the tracker server is not running during import.")
|
||||
print()
|
||||
|
||||
confirm = input("Continue with import? (y/N): ").lower().strip()
|
||||
if confirm != 'y':
|
||||
print("Import cancelled.")
|
||||
sys.exit(0)
|
||||
|
||||
success = asyncio.run(run_import(file_path))
|
||||
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue