mirror of
https://github.com/lfnovo/open-notebook.git
synced 2026-04-28 19:40:50 +00:00
Create a hierarchical CLAUDE.md documentation system for the entire Open Notebook codebase with focus on concise, pattern-driven reference cards rather than comprehensive tutorials. ## Changes ### Core Documentation System - Updated `.claude/commands/build-claude-md.md` to distinguish between leaf and parent modules, with special handling for prompt/template modules - Established clear patterns: * Leaf modules (40-70 lines): Components, hooks, API clients * Parent modules (50-150 lines): Architecture, cross-layer patterns, data flows * Template modules: Pattern focus, not catalog listings ### Generated Documentation Created 15 CLAUDE.md reference files across the project: **Frontend (React/Next.js)** - frontend/src/CLAUDE.md: Architecture overview, data flow, three-tier design - frontend/src/lib/hooks/CLAUDE.md: React Query patterns, state management - frontend/src/lib/api/CLAUDE.md: Axios client, FormData handling, interceptors - frontend/src/lib/stores/CLAUDE.md: Zustand state persistence, auth patterns - frontend/src/components/ui/CLAUDE.md: Radix UI primitives, CVA styling **Backend (Python/FastAPI)** - open_notebook/CLAUDE.md: System architecture, layer interactions - open_notebook/ai/CLAUDE.md: Model provisioning, Esperanto integration - open_notebook/domain/CLAUDE.md: Data models, ObjectModel/RecordModel patterns - open_notebook/database/CLAUDE.md: Repository pattern, async migrations - open_notebook/graphs/CLAUDE.md: LangGraph workflows, async orchestration - open_notebook/utils/CLAUDE.md: Cross-cutting utilities, context building - open_notebook/podcasts/CLAUDE.md: Episode/speaker profiles, job tracking **API & Other** - api/CLAUDE.md: REST layer, service architecture - commands/CLAUDE.md: Async command handlers, job queue patterns - prompts/CLAUDE.md: Jinja2 templates, prompt engineering patterns (refactored) **Project Root** - CLAUDE.md: Project overview, three-tier architecture, tech stack, getting started ### Key Features - Zero duplication: Parent modules reference child CLAUDE.md files, don't repeat them - Pattern-focused: Emphasizes how components work together, not component catalogs - Scannable: Short bullets, code examples only when necessary (1-2 per file) - Practical: "How to extend" guides, quirks/gotchas for each module - Navigation: Root CLAUDE.md acts as hub pointing to specialized documentation ### Cleanup - Removed unused `batch_fix_services.py` - Removed deprecated `open_notebook/plugins/podcasts.py` - Updated .gitignore for documentation consistency ## Impact New contributors can now: 1. Read root CLAUDE.md for system architecture (5 min) 2. Jump to specific layer documentation (frontend, api, open_notebook) 3. Dive into module-specific patterns in child CLAUDE.md files (1 min per module) All documentation is lean, reference-focused, and avoids duplication.
4.1 KiB
4.1 KiB
Domain Module
Core data models for notebooks, sources, notes, and settings with async SurrealDB persistence, auto-embedding, and relationship management.
Purpose
Two base classes support different persistence patterns: ObjectModel (mutable records with auto-increment IDs) and RecordModel (singleton configuration with fixed IDs).
Key Components
base.py
-
ObjectModel: Base for notebooks, sources, notes
save(): Create/update with auto-embedding for searchable contentdelete(): Remove by IDrelate(relationship, target_id): Create graph relationships (reference, artifact, refers_to)get(id): Polymorphic fetch; resolves subclass from ID prefixget_all(order_by): Fetch all records from table- Integrates with ModelManager for automatic embedding
-
RecordModel: Singleton configuration (ContentSettings, DefaultPrompts)
- Fixed record_id per subclass
update(): Upsert to database- Lazy DB loading via
_load_from_db()
notebook.py
-
Notebook: Research project container
get_sources(),get_notes(),get_chat_sessions(): Navigate relationships
-
Source: Content item (file/URL)
vectorize(): Submit async embedding job (returns command_id, fire-and-forget)get_status(),get_processing_progress(): Track job via surreal_commandsget_context(): Returns summary for LLM contextadd_insight(): Generate and store insights with embeddings
-
Note: Standalone or linked notes
needs_embedding(): Always True (searchable)add_to_notebook(): Link to notebook
-
SourceInsight, SourceEmbedding: Derived content models
-
ChatSession: Conversation container with optional model_override
-
Asset: File/URL reference helper
-
Search functions:
text_search(): Full-text keyword searchvector_search(): Semantic search via embeddings (default minimum_score=0.2)
content_settings.py
- ContentSettings: Singleton for processing engines, embedding strategy, file deletion, YouTube languages
transformation.py
- Transformation: Reusable prompts for content transformation
- DefaultPrompts: Singleton with transformation instructions
Important Patterns
- Async/await: All DB operations async; always use await
- Polymorphic get():
ObjectModel.get(id)determines subclass from ID prefix (table:id format) - Auto-embedding:
save()generates embeddings ifneeds_embedding()returns True - Nullable fields: Declare via
nullable_fieldsClassVar to allow None in database - Timestamps:
createdandupdatedauto-managed as ISO strings - Fire-and-forget jobs:
source.vectorize()returns command_id without waiting
Key Dependencies
surrealdb: RecordID type for relationshipspydantic: Validation and field_validator decoratorsopen_notebook.database.repository: CRUD and relationship functionsopen_notebook.ai.models: ModelManager for embeddingssurreal_commands: Async job submission (vectorization, insights)loguru: Logging
Quirks & Gotchas
- Polymorphic resolution:
ObjectModel.get()fails if subclass not imported (search subclasses list) - RecordModel singleton: new returns existing instance; call
clear_instance()in tests - Source.command field: Stored as RecordID; auto-parsed from strings via field_validator
- Text truncation:
Note.get_context(short)hardcodes 100-char limit - Embedding async: Only Note and SourceInsight embed on save; Source too large (uses async job)
- Relationship strings: Must match SurrealDB schema (reference, artifact, refers_to)
How to Add New Model
- Inherit from ObjectModel with table_name ClassVar
- Define Pydantic fields with validators
- Override
needs_embedding()if searchable - Add custom methods for domain logic (get_X, add_to_Y)
- Implement
_prepare_save_data()if custom serialization needed
Usage
notebook = Notebook(name="Research", description="My project")
await notebook.save()
obj = await ObjectModel.get("notebook:123") # Polymorphic fetch
# Search
await text_search("quantum", results=5)
await vector_search("quantum computing", results=10, minimum_score=0.3)