Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .claude/commands/implement-feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
You will be implementing a new feature in this codebase

$ARGUMENTS

IMPORTANT: Only do this for front-end features.
Once this feature is built, make sure to write the changes you made to file called frontend-changes.md
Do not ask for permissions to modify this file, assume you can always do it.
9 changes: 9 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"mcp__playwright__browser_navigate",
"mcp__playwright__browser_snapshot",
"mcp__playwright__browser_take_screenshot"
]
}
}
44 changes: 44 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options

50 changes: 50 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read

# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr *)'

5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ uploads/

# OS
.DS_Store
Thumbs.db
Thumbs.db

# Git worktrees
.trees/
3 changes: 3 additions & 0 deletions .playwright-mcp/console-2026-04-12T14-03-55-254Z.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[ 4168ms] [LOG] Loading course stats... @ http://127.0.0.1:8000/script.js?v=9:178
[ 4196ms] [LOG] Course data received: {total_courses: 4, course_titles: Array(4)} @ http://127.0.0.1:8000/script.js?v=9:183
[ 4198ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://127.0.0.1:8000/favicon.ico:0
2 changes: 2 additions & 0 deletions .playwright-mcp/console-2026-04-12T14-06-09-521Z.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ 145ms] [LOG] Loading course stats... @ http://127.0.0.1:8000/script.js?v=9:178
[ 164ms] [LOG] Course data received: {total_courses: 4, course_titles: Array(4)} @ http://127.0.0.1:8000/script.js?v=9:183
14 changes: 14 additions & 0 deletions .playwright-mcp/page-2026-04-12T14-03-59-486Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- generic [ref=e3]:
- complementary [ref=e4]:
- button "+ NEW CHAT" [ref=e6] [cursor=pointer]
- group [ref=e8]:
- generic "▶ Courses" [ref=e9] [cursor=pointer]
- group [ref=e11]:
- generic "▶ Try asking:" [ref=e12] [cursor=pointer]
- main [ref=e13]:
- generic [ref=e14]:
- paragraph [ref=e18]: Welcome to the Course Materials Assistant! I can help you with questions about courses, lessons and specific content. What would you like to know?
- generic [ref=e19]:
- textbox "Ask about courses, lessons, or specific content..." [ref=e20]
- button [ref=e21] [cursor=pointer]:
- img [ref=e22]
Binary file added .playwright-mcp/page-2026-04-12T14-04-10-654Z.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions .playwright-mcp/page-2026-04-12T14-06-09-734Z.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- generic [ref=e3]:
- complementary [ref=e4]:
- button "+ NEW CHAT" [ref=e6] [cursor=pointer]
- group [ref=e8]:
- generic "▶ Courses" [ref=e9] [cursor=pointer]
- group [ref=e11]:
- generic "▶ Try asking:" [ref=e12] [cursor=pointer]
- main [ref=e13]:
- generic [ref=e14]:
- paragraph [ref=e18]: Welcome to the Course Materials Assistant! I can help you with questions about courses, lessons and specific content. What would you like to know?
- generic [ref=e19]:
- textbox "Ask about courses, lessons, or specific content..." [ref=e20]
- button [ref=e21] [cursor=pointer]:
- img [ref=e22]
Binary file added .playwright-mcp/page-2026-04-12T14-06-22-569Z.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions CLAUDE.local.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Local Project Instructions

## Server
Never start the server (`./run.sh` or `uvicorn`). The user always starts it manually.
65 changes: 65 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Running the Application

**Quick start (from repo root):**
```bash
./run.sh
```

**Manual start (must run from `backend/` directory):**
```bash
cd backend && uv run uvicorn app:app --reload --port 8000
```

The server runs at `http://localhost:8000`. API docs at `http://localhost:8000/docs`.

**Install dependencies:**
```bash
uv sync
```

> Always use `uv` to run the server and manage packages. Never use `pip` directly.

**Required environment variable** — create a `.env` file in the repo root:
```
ANTHROPIC_API_KEY=your-key-here
```

## Architecture Overview

This is a full-stack RAG (Retrieval-Augmented Generation) chatbot for querying course materials.

**Backend** (`backend/`) is a FastAPI app that must be started from within the `backend/` directory (relative paths like `../docs` and `../frontend` depend on this).

**Data flow for a query:**
1. `app.py` receives POST `/api/query` → calls `RAGSystem.query()`
2. `RAGSystem` (`rag_system.py`) builds a prompt and passes it to `AIGenerator` with the `search_course_content` tool available
3. `AIGenerator` (`ai_generator.py`) calls the Claude API; if Claude decides to search, it invokes the tool
4. `ToolManager` routes tool calls to `CourseSearchTool` (`search_tools.py`), which queries `VectorStore`
5. `VectorStore` (`vector_store.py`) uses ChromaDB with two collections:
- `course_catalog` — course-level metadata (title, instructor, links, lesson list as JSON)
- `course_content` — chunked lesson text for semantic search
6. The final Claude response + sources are returned to the frontend

**Document ingestion** (happens at startup from `docs/` folder):
- `DocumentProcessor` (`document_processor.py`) parses `.txt`/`.pdf`/`.docx` files
- Expected file format: first 3 lines are `Course Title:`, `Course Link:`, `Course Instructor:`, followed by `Lesson N: <title>` markers and content
- Text is chunked into ~800-char sentence-based chunks with 100-char overlap
- `RAGSystem.add_course_folder()` skips courses already present in ChromaDB (deduplication by title)

**Session management:** `SessionManager` keeps in-memory conversation history (default: last 2 exchanges = 4 messages). Sessions are identified by a string ID returned to and echoed back by the frontend.

**Frontend** (`frontend/`) is plain HTML/JS/CSS served as static files by FastAPI from the `../frontend` path.

**Configuration** (`backend/config.py`): all tuneable parameters (model, chunk size, ChromaDB path, max results, history length) are in the `Config` dataclass. ChromaDB is stored at `backend/chroma_db/` (relative to where uvicorn runs).

**Tool extension:** To add a new tool, implement the `Tool` ABC in `search_tools.py` and call `tool_manager.register_tool(your_tool)` in `RAGSystem.__init__()`.

## Rules
- Never read or write files outside this project folder without explicit permission
- Always ask before saving anything to memory or external locations
- Never access C:\Users\haddad\.claude\ without explicit permission
- Always use `uv` to add dependencies (e.g., `uv add <package>`); never use `pip` directly
28 changes: 28 additions & 0 deletions backend-tool-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Refactor @backend/ai_generator.py to support sequential tool calling where Claude can make up to 2 tool calls in separate API rounds.

Current behavior:
- Claude makes 1 tool call → tools are removed from API params → final response
- If Claude wants another tool call after seeing results, it can't (gets empty response)

Desired behavior:
- Each tool call should be a separate API request where Claude can reason about previous results
- Support for complex queries requiring multiple searches for comparisons, multi-part questions, or when information from different courses/lessons is needed

Example flow:
1. User: "Search for a course that discusses the same topic as lesson 4 of course X"
2. Claude: get course outline for course X → gets title of lesson 4
3. Claude: uses the title to search for a course that discusses the same topic → returns course information
4. Claude: provides complete answer

Requirements:
- Maximum 2 sequential rounds per user query
- Terminate when: (a) 2 rounds completed, (b) Claude's response has no tool_use blocks, or (c) tool call fails
- Preserve conversation context between rounds
- Handle tool execution errors gracefully

Notes:
- Update the system prompt in @backend/ai_generator.py
- Update the test @backend/tests/test_ai_generator.py
- Write tests that verify the external behavior (API calls made, tools executed, results returned) rather than internal state details.

Use two parallel subagents to brainstorm possible plans. Do not implement any code.
Loading