feat(api): implement notebook management CRUD endpoints

Implement Sprint 1: Notebook Management CRUD

- Add NotebookService with full CRUD operations
- Add POST /api/v1/notebooks (create notebook)
- Add GET /api/v1/notebooks (list with pagination)
- Add GET /api/v1/notebooks/{id} (get by ID)
- Add PATCH /api/v1/notebooks/{id} (partial update)
- Add DELETE /api/v1/notebooks/{id} (delete)
- Add Pydantic models for requests/responses
- Add custom exceptions (ValidationError, NotFoundError, NotebookLMError)
- Add comprehensive unit tests (31 tests, 97% coverage)
- Add API integration tests (26 tests)
- Fix router prefix duplication
- Fix JSON serialization in error responses

BREAKING CHANGE: None
This commit is contained in:
Luca Sacchi Ricciardi
2026-04-06 01:13:13 +02:00
commit 4b7a419a98
65 changed files with 10507 additions and 0 deletions

492
AGENTS.md Normal file
View File

@@ -0,0 +1,492 @@
# Repository Guidelines - NotebookLM Agent API
**Status:** Active
**Last Updated:** 2026-04-05
**Project:** NotebookLM Agent API
---
## 1. Project Structure & Module Organization
```
├── src/
│ └── notebooklm_agent/ # Main package
│ ├── __init__.py
│ ├── api/ # FastAPI application
│ │ ├── __init__.py
│ │ ├── main.py # FastAPI app entry
│ │ ├── routes/ # API routes
│ │ │ ├── __init__.py
│ │ │ ├── notebooks.py
│ │ │ ├── sources.py
│ │ │ ├── chat.py
│ │ │ ├── generate.py
│ │ │ ├── artifacts.py
│ │ │ └── webhooks.py
│ │ ├── models/ # Pydantic models
│ │ │ ├── __init__.py
│ │ │ ├── requests.py
│ │ │ └── responses.py
│ │ └── dependencies.py # FastAPI dependencies
│ ├── services/ # Business logic
│ │ ├── __init__.py
│ │ ├── notebook_service.py
│ │ ├── source_service.py
│ │ ├── chat_service.py
│ │ ├── artifact_service.py
│ │ └── webhook_service.py
│ ├── core/ # Core utilities
│ │ ├── __init__.py
│ │ ├── config.py # Configuration management
│ │ ├── exceptions.py # Custom exceptions
│ │ ├── logging.py # Logging setup
│ │ └── security.py # Security utilities
│ ├── webhooks/ # Webhook system
│ │ ├── __init__.py
│ │ ├── dispatcher.py
│ │ ├── validator.py
│ │ └── retry.py
│ └── skill/ # AI Skill interface
│ ├── __init__.py
│ └── handler.py
├── tests/
│ ├── __init__.py
│ ├── unit/ # Unit tests
│ │ ├── __init__.py
│ │ ├── test_services/
│ │ └── test_core/
│ ├── integration/ # Integration tests
│ │ ├── __init__.py
│ │ └── test_api/
│ └── e2e/ # End-to-end tests
│ ├── __init__.py
│ └── test_workflows/
├── docs/ # Documentation
│ ├── api/ # API documentation
│ └── examples/ # Code examples
├── scripts/ # Utility scripts
├── .github/ # GitHub workflows
├── pyproject.toml # Project configuration
├── .pre-commit-config.yaml # Pre-commit hooks
├── CHANGELOG.md # Changelog
├── CONTRIBUTING.md # Contribution guidelines
├── SKILL.md # AI Agent skill definition
└── prd.md # Product Requirements Document
```
---
## 2. Development Environment Setup
### 2.1 Initial Setup
```bash
# Clone repository
git clone <repository-url>
cd notebooklm-agent-api
# Create virtual environment with uv
uv venv --python 3.10
source .venv/bin/activate # Linux/Mac
# or: .venv\Scripts\activate # Windows
# Install dependencies
uv sync --extra dev --extra browser
# Install pre-commit hooks
uv run pre-commit install
# Verify setup
uv run pytest --version
uv run python -c "import notebooklm_agent; print('OK')"
```
### 2.2 Environment Variables
Create `.env` file:
```env
# API Configuration
NOTEBOOKLM_AGENT_API_KEY=your-api-key
NOTEBOOKLM_AGENT_WEBHOOK_SECRET=your-webhook-secret
NOTEBOOKLM_AGENT_PORT=8000
NOTEBOOKLM_AGENT_HOST=0.0.0.0
# NotebookLM Configuration
NOTEBOOKLM_HOME=~/.notebooklm
NOTEBOOKLM_PROFILE=default
# Logging
LOG_LEVEL=INFO
LOG_FORMAT=json
# Development
DEBUG=true
TESTING=false
```
---
## 3. Build, Test, and Development Commands
### 3.1 Testing
```bash
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=src/notebooklm_agent --cov-report=term-missing
# Run specific test category
uv run pytest tests/unit/
uv run pytest tests/integration/
uv run pytest tests/e2e/ -m e2e
# Run with verbose output
uv run pytest -v
# Run failing tests only
uv run pytest --lf
# Record VCR cassettes
NOTEBOOKLM_VCR_RECORD=1 uv run pytest tests/integration/ -v
```
### 3.2 Code Quality
```bash
# Run linter
uv run ruff check src/ tests/
# Fix auto-fixable issues
uv run ruff check --fix src/ tests/
# Format code
uv run ruff format src/ tests/
# Type checking
uv run mypy src/notebooklm_agent
# Run all quality checks
uv run ruff check src/ tests/ && uv run ruff format --check src/ tests/ && uv run mypy src/notebooklm_agent
```
### 3.3 Pre-commit
```bash
# Run all hooks on all files
uv run pre-commit run --all-files
# Run specific hook
uv run pre-commit run ruff --all-files
uv run pre-commit run mypy --all-files
```
### 3.4 Running the Application
```bash
# Development server with auto-reload
uv run python -m notebooklm_agent.api.main --reload
# Production server
uv run gunicorn notebooklm_agent.api.main:app -w 4 -k uvicorn.workers.UvicornWorker
# Using FastAPI CLI
uv run fastapi dev src/notebooklm_agent/api/main.py
```
---
## 4. Coding Style & Naming Conventions
### 4.1 General Guidelines
- **Python Version:** 3.10+
- **Indentation:** 4 spaces
- **Quotes:** Double quotes for strings
- **Line Length:** 100 characters
- **Type Hints:** Required for all function signatures
### 4.2 Naming Conventions
| Element | Convention | Example |
|---------|------------|---------|
| Modules | snake_case | `notebook_service.py` |
| Classes | PascalCase | `NotebookService` |
| Functions | snake_case | `create_notebook()` |
| Variables | snake_case | `notebook_id` |
| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
| Private | _prefix | `_internal_helper()` |
### 4.3 Import Order (enforced by ruff)
```python
# 1. Standard library
import json
from typing import List, Optional
# 2. Third-party
import httpx
from fastapi import FastAPI
# 3. First-party
from notebooklm_agent.core.config import Settings
from notebooklm_agent.services.notebook_service import NotebookService
```
### 4.4 Documentation
- All public modules, classes, and functions must avere docstrings
- Use Google-style docstrings
- Include type information in docstrings when complesso
Example:
```python
async def create_notebook(
title: str,
description: Optional[str] = None
) -> NotebookResponse:
"""Create a new NotebookLM notebook.
Args:
title: The notebook title (max 100 chars).
description: Optional notebook description.
Returns:
NotebookResponse with notebook details.
Raises:
ValidationError: If title is invalid.
NotebookLMError: If NotebookLM API fails.
"""
```
---
## 5. Testing Guidelines
### 5.1 Test Organization
```
tests/
├── unit/ # Pure logic, no external calls
├── integration/ # With mocked external APIs
└── e2e/ # Full workflows, real APIs
```
### 5.2 Test Naming
- Test files: `test_<module_name>.py`
- Test functions: `test_<behavior>_<condition>_<expected>`
Example:
```python
def test_create_notebook_valid_title_returns_created():
...
def test_create_notebook_empty_title_raises_validation_error():
...
```
### 5.3 Test Structure (AAA Pattern)
```python
async def test_create_notebook_success():
# Arrange
title = "Test Notebook"
service = NotebookService()
# Act
result = await service.create_notebook(title)
# Assert
assert result.title == title
assert result.id is not None
```
### 5.4 Markers
```python
import pytest
@pytest.mark.unit
def test_pure_function():
...
@pytest.mark.integration
def test_with_http_client():
...
@pytest.mark.e2e
def test_full_workflow():
...
@pytest.mark.asyncio
async def test_async_function():
...
```
---
## 6. Commit, PR, and Workflow
### 6.1 Conventional Commits
Format: `<type>(<scope>): <description>`
**Types:**
- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation only
- `style`: Code style (formatting, semicolons, etc.)
- `refactor`: Code refactoring
- `test`: Adding or correcting tests
- `chore`: Build process, dependencies
- `ci`: CI/CD changes
**Scopes:**
- `api`: REST API endpoints
- `webhook`: Webhook system
- `skill`: AI skill interface
- `notebook`: Notebook operations
- `source`: Source management
- `artifact`: Artifact generation
- `auth`: Authentication
- `core`: Core utilities
**Examples:**
```
feat(api): add webhook registration endpoint
fix(webhook): retry logic exponential backoff
refactor(notebook): extract validation logic
test(source): add unit tests for URL validation
docs(api): update OpenAPI schema
chore(deps): upgrade notebooklm-py to 0.3.4
```
### 6.2 Commit Message Format
```
<type>(<scope>): <short summary>
[optional body: explain what and why, not how]
[optional footer: BREAKING CHANGE, Fixes #123, etc.]
```
### 6.3 Pull Request Process
1. Create feature branch from `main`
2. Make commits following conventional commits
3. Ensure all tests pass: `uv run pytest`
4. Ensure code quality: `uv run pre-commit run --all-files`
5. Update CHANGELOG.md if applicable
6. Create PR with template
7. Require 1+ review approval
8. Squash and merge
### 6.4 Branch Naming
- Feature: `feat/description`
- Bugfix: `fix/description`
- Hotfix: `hotfix/description`
- Release: `release/v1.0.0`
---
## 7. API Design Guidelines
### 7.1 RESTful Endpoints
- Use nouns, not verbs: `/notebooks` not `/createNotebook`
- Use plural nouns: `/notebooks` not `/notebook`
- Use HTTP methods appropriately:
- GET: Read
- POST: Create
- PUT/PATCH: Update
- DELETE: Remove
### 7.2 Response Format
```json
{
"success": true,
"data": { ... },
"meta": {
"timestamp": "2026-04-05T10:30:00Z",
"request_id": "uuid"
}
}
```
### 7.3 Error Format
```json
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid notebook title",
"details": [...]
},
"meta": {
"timestamp": "2026-04-05T10:30:00Z",
"request_id": "uuid"
}
}
```
---
## 8. Webhook Guidelines
### 8.1 Event Naming
- Format: `<resource>.<action>`
- Examples: `notebook.created`, `source.ready`, `artifact.completed`
### 8.2 Webhook Payload
```json
{
"event": "source.ready",
"timestamp": "2026-04-05T10:30:00Z",
"data": {
"notebook_id": "uuid",
"source_id": "uuid",
"source_title": "..."
}
}
```
### 8.3 Security
- Always sign with HMAC-SHA256
- Include `X-Webhook-Signature` header
- Verify signature before processing
---
## 9. Agent Notes
### 9.1 Parallel Agent Safety
When running multiple agents:
1. Use explicit notebook IDs: `-n <notebook_id>`
2. Isolate with profiles: `NOTEBOOKLM_PROFILE=agent-$ID`
3. Or isolate with home: `NOTEBOOKLM_HOME=/tmp/agent-$ID`
### 9.2 Common Commands
```bash
# Check status
notebooklm status
# Verify auth
notebooklm auth check
# Health check
uv run python -c "from notebooklm_agent.api.main import health_check; print(health_check())"
```
### 9.3 Troubleshooting
```bash
# Reset auth
notebooklm login
# Clear cache
rm -rf ~/.notebooklm/cache
# Verbose logging
LOG_LEVEL=DEBUG uv run python -m notebooklm_agent.api.main
```
---
## 10. Resources
- **PRD:** `prd.md`
- **Skill Definition:** `SKILL.md`
- **Contributing:** `CONTRIBUTING.md`
- **Changelog:** `CHANGELOG.md`
- **API Docs:** `/docs` (when server running)
- **OpenAPI Schema:** `/openapi.json`
---
**Maintained by:** NotebookLM Agent Team
**Last Updated:** 2026-04-05