Documentation Guide¶
This guide covers writing documentation for Echomine, including docstrings, user guides, and API reference.
Documentation Types¶
1. API Reference (Auto-Generated)¶
Generated automatically from Python docstrings using mkdocstrings:
- Source: Docstrings in
src/echomine/ - Output:
docs/api/pages - Updates: Automatic when code changes
2. User Guides (Manual)¶
Written manually in Markdown:
- Source:
docs/*.mdfiles - Examples: quickstart.md, cli-usage.md, library-usage.md
- Updates: Manual when features change
3. Developer Docs (Manual)¶
This section and related guides:
- Source:
docs/development/,docs/maintaining/ - Updates: Manual when processes change
Docstring Format (Google Style)¶
Echomine uses Google-style docstrings for consistency with mkdocstrings.
Function Docstring¶
def search(
self,
file_path: Path,
query: SearchQuery,
*,
progress_callback: Optional[Callable[[int], None]] = None,
) -> Iterator[SearchResult[Conversation]]:
"""Search conversations matching query criteria with BM25 ranking.
Streams through the export file and returns matching conversations
ranked by relevance score. Uses O(1) memory regardless of file size.
Args:
file_path: Path to OpenAI export JSON file.
query: Search parameters including keywords, date filters, and limit.
progress_callback: Optional callback invoked with count of processed
conversations. Called every 100 items or 100ms.
Yields:
SearchResult containing matched conversation and relevance score (0.0-1.0).
Results are yielded in descending order by score.
Raises:
FileNotFoundError: If file_path does not exist.
PermissionError: If file is not readable.
ParseError: If export format is invalid or unsupported.
Example:
```python
from echomine import OpenAIAdapter, SearchQuery
from pathlib import Path
adapter = OpenAIAdapter()
query = SearchQuery(keywords=["python", "algorithm"], limit=10)
for result in adapter.search(Path("export.json"), query):
print(f"{result.score:.2f}: {result.conversation.title}")
```
Note:
The search uses BM25 ranking algorithm. Title-only searches
(no keywords) skip full-text ranking for better performance.
See Also:
- `stream_conversations`: For unfiltered iteration
- `get_conversation_by_id`: For direct ID lookup
"""
Class Docstring¶
class OpenAIAdapter:
"""Adapter for parsing and searching OpenAI ChatGPT exports.
Implements the ConversationProvider protocol for ChatGPT export files.
Stateless design allows reuse across multiple files.
The adapter handles:
- Streaming conversations with O(1) memory usage
- BM25-ranked keyword search
- Date range and title filtering
- Graceful handling of malformed entries
Attributes:
None. This adapter is stateless by design.
Example:
```python
from echomine import OpenAIAdapter
from pathlib import Path
adapter = OpenAIAdapter()
# List all conversations
for conv in adapter.stream_conversations(Path("export.json")):
print(conv.title)
# Search with keywords
from echomine import SearchQuery
query = SearchQuery(keywords=["python"])
for result in adapter.search(Path("export.json"), query):
print(f"{result.score:.2f}: {result.conversation.title}")
```
Note:
OpenAI exports use a specific JSON schema. This adapter supports
the current export format as of 2024. Future format changes may
require adapter updates.
See Also:
- `ConversationProvider`: The protocol this adapter implements
- `Conversation`: The data model returned by this adapter
"""
Property Docstring¶
@property
def message_count(self) -> int:
"""Total number of messages across all branches.
Counts all messages in the conversation tree, including
messages in alternate branches.
Returns:
Non-negative integer count of messages.
Example:
```python
conv = adapter.get_conversation_by_id(path, conv_id)
print(f"Conversation has {conv.message_count} messages")
```
"""
return len(self.messages)
Module Docstring¶
"""OpenAI ChatGPT export adapter.
This module provides the OpenAIAdapter class for parsing and searching
ChatGPT conversation exports.
Example:
```python
from echomine.adapters.openai import OpenAIAdapter
adapter = OpenAIAdapter()
for conv in adapter.stream_conversations(Path("export.json")):
print(conv.title)
```
Typical usage:
1. Create adapter instance (stateless, reusable)
2. Call stream_conversations() for listing
3. Call search() for filtered/ranked results
4. Call get_conversation_by_id() for specific lookup
See Also:
- `echomine.protocols.ConversationProvider`: Protocol definition
- `echomine.models.Conversation`: Data model
"""
MkDocs Configuration¶
mkdocs.yml Structure¶
site_name: Echomine
nav:
- Home: index.md
- Getting Started:
- Installation: installation.md
- Quickstart: quickstart.md
- User Guide:
- CLI Usage: cli-usage.md
- Library Usage: library-usage.md
- API Reference:
- api/index.md
- Models:
- Conversation: api/models/conversation.md
- Message: api/models/message.md
- Adapters:
- OpenAI: api/adapters/openai.md
- Development:
- development/index.md
- Setup: development/setup.md
- Testing: development/testing.md
theme:
name: material
features:
- content.code.copy
- navigation.sections
plugins:
- search
- mkdocstrings:
handlers:
python:
options:
docstring_style: google
show_source: true
API Reference Pages¶
Create stub pages that pull from docstrings:
<!-- docs/api/adapters/openai.md -->
# OpenAI Adapter
::: echomine.adapters.openai.OpenAIAdapter
options:
show_root_heading: true
show_source: true
members:
- stream_conversations
- search
- get_conversation_by_id
Writing User Guides¶
Structure¶
- Start with "why": What problem does this solve?
- Quick example: Working code immediately
- Detailed explanation: Step-by-step guide
- Advanced usage: Edge cases, options
- Troubleshooting: Common issues
Example Page Structure¶
# Feature Name
Brief description of what this feature does and why you'd use it.
## Quick Start
\`\`\`python
# Minimal working example
from echomine import OpenAIAdapter
adapter = OpenAIAdapter()
\`\`\`
## Basic Usage
### Step 1: Setup
Explanation...
### Step 2: Execute
Explanation...
## Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| limit | int | 10 | Maximum results |
## Examples
### Example: Search by Keywords
\`\`\`python
# Full example with context
\`\`\`
### Example: Filter by Date
\`\`\`python
# Another example
\`\`\`
## Troubleshooting
### Error: FileNotFoundError
**Cause**: File path doesn't exist.
**Solution**: Verify the path...
## See Also
- [Related Feature](other-page.md)
- [API Reference](api/module.md)
Building Documentation¶
Local Development¶
# Install docs dependencies
pip install -e ".[dev]"
# Serve with live reload
mkdocs serve
# View at http://127.0.0.1:8000
# Build static site
mkdocs build
# Output in site/ directory
Checking for Issues¶
# Build with strict mode (fails on warnings)
mkdocs build --strict
# Common warnings:
# - Broken links
# - Missing pages in nav
# - Invalid markdown
Deployment¶
Documentation deploys automatically via GitHub Actions when pushed to main:
git add docs/
git commit -m "docs: update user guide"
git push origin main
# GitHub Actions runs mkdocs gh-deploy
Style Guidelines¶
Do¶
- Use active voice ("Returns the count" not "The count is returned")
- Include working code examples
- Document all public APIs
- Keep examples minimal but complete
- Link to related documentation
Don't¶
- Document private methods (prefix with
_) - Repeat type information in description
- Use jargon without explanation
- Leave placeholder TODOs in docs
Code Examples¶
# Good: Complete, runnable example
from echomine import OpenAIAdapter, SearchQuery
from pathlib import Path
adapter = OpenAIAdapter()
query = SearchQuery(keywords=["python"], limit=5)
results = list(adapter.search(Path("export.json"), query))
print(f"Found {len(results)} results")
# Bad: Incomplete, won't run
results = adapter.search(path, query) # What's adapter? path? query?
Updating Documentation¶
When to Update¶
- New features: Add to user guide + API reference
- Changed behavior: Update affected pages
- Bug fixes: Update if behavior was documented incorrectly
- Breaking changes: Add migration guide
Checklist¶
- Docstrings updated for changed functions
- User guide reflects new behavior
- Examples still work
- Links not broken
-
mkdocs build --strictpasses
Next Steps¶
- Testing Guide: Writing tests
- Type Checking: Type hints
- Contributing: Full contribution guide
Last Updated: 2025-11-30