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:
Ryan Malloy 2025-08-11 05:58:27 -06:00
parent 166247bf70
commit bec1606c86
27 changed files with 6150 additions and 32 deletions

View file

@ -83,6 +83,54 @@ async def log_conversation(
)
@router.get("/conversations", response_model=List[ConversationSearchResult])
async def get_conversations(
project_id: Optional[int] = Query(None, description="Filter by project ID"),
limit: int = Query(50, description="Maximum number of results"),
offset: int = Query(0, description="Number of results to skip"),
db: AsyncSession = Depends(get_db)
):
"""
Get recent conversations with optional project filtering.
"""
try:
# Build query
query = select(Conversation).options(
selectinload(Conversation.session).selectinload(Session.project)
)
# Add project filter if specified
if project_id:
query = query.join(Session).where(Session.project_id == project_id)
# Order by timestamp descending, add pagination
query = query.order_by(Conversation.timestamp.desc()).offset(offset).limit(limit)
result = await db.execute(query)
conversations = result.scalars().all()
# Convert to response format
results = []
for conversation in conversations:
results.append(ConversationSearchResult(
id=conversation.id,
project_name=conversation.session.project.name,
timestamp=conversation.timestamp,
user_prompt=conversation.user_prompt,
claude_response=conversation.claude_response,
relevance_score=1.0, # All results are equally relevant when just listing
context=[] # No context snippets needed for listing
))
return results
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to get conversations: {str(e)}"
)
@router.get("/conversations/search", response_model=List[ConversationSearchResult])
async def search_conversations(
query: str = Query(..., description="Search query"),