Skip to main content
Glama
05-api-detailed-spec.md29.3 kB
# SafeMarkdownEditor API: Detailed Technical Specification ## Table of Contents 1. [Overview](#overview) 2. [Core Data Types](#core-data-types) 3. [API Interface](#api-interface) 4. [Operation Semantics](#operation-semantics) 5. [Error Handling](#error-handling) 6. [Thread Safety](#thread-safety) 7. [Performance Characteristics](#performance-characteristics) 8. [Usage Examples](#usage-examples) 9. [Migration Guide](#migration-guide) 10. [Implementation Notes](#implementation-notes) ## Overview The `SafeMarkdownEditor` API provides atomic, thread-safe operations for editing Markdown documents with comprehensive validation, error recovery, and transaction support. It is built on top of the `QuantalogicMarkdownParser` and provides a high-level, semantic interface that abstracts away the complexity of token manipulation. ### Design Principles 1. **Safety First**: All operations are atomic with automatic rollback on failure 2. **Immutable References**: Section references remain stable across document modifications 3. **Rich Feedback**: Comprehensive error reporting with actionable suggestions 4. **Preview-Driven**: All operations support preview before application 5. **Thread Safety**: Concurrent access protection with proper synchronization 6. **Validation-Centric**: Structural integrity maintained at all times ### Version Information - **API Version**: 2.0.0 - **Compatibility**: Backward compatible with legacy `MarkdownEditor` via deprecation layer - **Dependencies**: `quantalogic-markdown-mcp >= 0.1.0` ## Core Data Types ### SectionReference Immutable reference to a document section that remains stable across edits. ```python @dataclass(frozen=True) class SectionReference: """Immutable reference to a document section.""" id: str # Stable hash-based identifier title: str # Section heading text level: int # Heading level (1-6) line_start: int # Starting line number (0-indexed) line_end: int # Ending line number (0-indexed) path: List[str] # Hierarchical path from root def __hash__(self) -> int: """Hash based on immutable properties.""" return hash((self.id, self.title, self.level, self.line_start)) def __eq__(self, other) -> bool: """Equality based on ID and position.""" return (isinstance(other, SectionReference) and self.id == other.id and self.line_start == other.line_start) ``` **Properties:** - `id`: Unique identifier computed from `hash(title + level + content_hash) % 100000` - `title`: Exact heading text without markup (e.g., "Introduction") - `level`: Heading level from 1 (H1) to 6 (H6) - `line_start`: Zero-indexed line where section begins - `line_end`: Zero-indexed line where section ends (exclusive) - `path`: Hierarchical navigation path (e.g., `["Chapter 1", "Introduction"]`) ### EditOperation Enumeration of supported editing operations. ```python class EditOperation(Enum): """Supported editing operations.""" INSERT_SECTION = "insert_section" UPDATE_SECTION = "update_section" DELETE_SECTION = "delete_section" MOVE_SECTION = "move_section" CHANGE_HEADING_LEVEL = "change_heading_level" INSERT_CONTENT = "insert_content" DELETE_CONTENT = "delete_content" BATCH_OPERATIONS = "batch_operations" ``` ### EditResult Comprehensive result object for all editing operations. ```python @dataclass class EditResult: """Result of an edit operation with comprehensive feedback.""" success: bool # Operation success status operation: EditOperation # Type of operation performed modified_sections: List[SectionReference] # Sections affected by operation errors: List[ParseError] # Validation or execution errors warnings: List[ParseError] # Non-critical issues preview: Optional[str] = None # Markdown preview of changes metadata: Dict[str, Any] = field(default_factory=dict) # Operation metadata @property def has_errors(self) -> bool: """Check if operation encountered errors.""" return len(self.errors) > 0 @property def has_warnings(self) -> bool: """Check if operation generated warnings.""" return len(self.warnings) > 0 def get_error_summary(self) -> str: """Get formatted summary of all errors.""" if not self.has_errors: return "No errors" return "\n".join(f"- {error}" for error in self.errors) ``` ### EditTransaction Container for atomic transaction operations with rollback capability. ```python @dataclass class EditTransaction: """Atomic transaction with rollback capability.""" transaction_id: str # Unique transaction identifier operations: List[Dict[str, Any]] # List of operations in transaction rollback_data: str # Document state for rollback timestamp: datetime # Transaction creation time metadata: Dict[str, Any] = field(default_factory=dict) # Transaction metadata def can_rollback(self) -> bool: """Check if transaction supports rollback.""" return bool(self.rollback_data) ``` ## API Interface ### Constructor ```python class SafeMarkdownEditor: def __init__(self, markdown_text: str, validation_level: ValidationLevel = ValidationLevel.STRICT, max_transaction_history: int = 100) -> None: """ Initialize safe markdown editor. Args: markdown_text: Initial markdown document content validation_level: Strictness of validation (STRICT, NORMAL, PERMISSIVE) max_transaction_history: Maximum number of transactions to retain Raises: ValueError: If markdown_text contains critical parsing errors DocumentStructureError: If document structure is invalid """ ``` ### Core Operations #### Document Inspection ```python def get_sections(self) -> List[SectionReference]: """ Get immutable references to all document sections. Returns: List of SectionReference objects in document order Complexity: O(n) where n is number of headings Thread Safety: Safe for concurrent access """ def get_section_by_id(self, section_id: str) -> Optional[SectionReference]: """ Find section by stable identifier. Args: section_id: Stable section identifier Returns: SectionReference if found, None otherwise Complexity: O(n) where n is number of sections """ def get_sections_by_level(self, level: int) -> List[SectionReference]: """ Get all sections at specified heading level. Args: level: Heading level (1-6) Returns: List of sections at specified level Raises: ValueError: If level not in range 1-6 """ def get_child_sections(self, parent: SectionReference) -> List[SectionReference]: """ Get all direct child sections of a parent section. Args: parent: Parent section reference Returns: List of immediate child sections """ ``` #### Preview Operations ```python def preview_operation(self, operation: EditOperation, **params) -> EditResult: """ Preview an operation without applying changes. Args: operation: Type of operation to preview **params: Operation-specific parameters Returns: EditResult with preview content and validation results Example: preview = editor.preview_operation( EditOperation.UPDATE_SECTION, section_ref=section, content="New content" ) """ def preview_batch_operations(self, operations: List[Dict[str, Any]]) -> EditResult: """ Preview multiple operations as atomic batch. Args: operations: List of operation dictionaries Returns: EditResult with combined preview and validation """ ``` #### Section Operations ```python def update_section_content(self, section_ref: SectionReference, content: str, preserve_subsections: bool = True) -> EditResult: """ Update content of a specific section. Args: section_ref: Immutable reference to target section content: New content (markdown text without heading) preserve_subsections: Whether to keep existing subsections Returns: EditResult with operation status and details Validation: - Validates content is valid markdown - Ensures no heading conflicts - Checks document structure integrity Atomicity: - Operation is fully atomic - Automatic rollback on any failure - Document state preserved on error """ def insert_section_after(self, after_section: SectionReference, level: int, title: str, content: str = "", auto_adjust_level: bool = True) -> EditResult: """ Insert new section after specified section. Args: after_section: Reference section for insertion point level: Heading level for new section (1-6) title: Section title (plain text) content: Section content (markdown) auto_adjust_level: Auto-adjust level to maintain hierarchy Returns: EditResult with new section reference in modified_sections Validation: - Ensures valid heading hierarchy - Validates title is non-empty - Checks content for structural issues """ def insert_section_before(self, before_section: SectionReference, level: int, title: str, content: str = "") -> EditResult: """Insert new section before specified section.""" def delete_section(self, section_ref: SectionReference, cascade_children: bool = True, soft_delete: bool = False) -> EditResult: """ Delete section and optionally its children. Args: section_ref: Section to delete cascade_children: Whether to delete child sections soft_delete: Mark for deletion without removing (future feature) Returns: EditResult with list of deleted sections Behavior: - If cascade_children=True: Deletes section and all subsections - If cascade_children=False: Promotes children to parent level - Maintains document structure integrity """ def move_section(self, section_ref: SectionReference, target_position: int, adjust_level: bool = True) -> EditResult: """ Move section to new position in document. Args: section_ref: Section to move target_position: New position (0-based index) adjust_level: Auto-adjust heading level for new context Returns: EditResult with updated section reference """ def change_heading_level(self, section_ref: SectionReference, new_level: int, cascade_children: bool = True) -> EditResult: """ Change heading level of section. Args: section_ref: Section to modify new_level: New heading level (1-6) cascade_children: Adjust child section levels proportionally Returns: EditResult with updated section hierarchy Validation: - Ensures valid heading hierarchy after change - Prevents invalid nesting structures """ ``` #### Content Operations ```python def insert_content_at_line(self, line_number: int, content: str) -> EditResult: """Insert content at specific line number.""" def delete_content_range(self, start_line: int, end_line: int) -> EditResult: """Delete content in specified line range.""" def replace_content_range(self, start_line: int, end_line: int, new_content: str) -> EditResult: """Replace content in specified range.""" ``` #### Batch Operations ```python def execute_batch_operations(self, operations: List[Dict[str, Any]], stop_on_error: bool = True) -> EditResult: """ Execute multiple operations atomically. Args: operations: List of operation specifications stop_on_error: Whether to halt on first error Returns: EditResult with combined results Atomicity: - All operations succeed or all are rolled back - No partial state changes - Transaction logged for rollback Example: operations = [ { 'operation': EditOperation.UPDATE_SECTION, 'section_ref': section1, 'content': 'New content 1' }, { 'operation': EditOperation.INSERT_SECTION, 'after_section': section2, 'level': 2, 'title': 'New Section', 'content': 'Section content' } ] result = editor.execute_batch_operations(operations) """ ``` #### Transaction Management ```python def get_transaction_history(self, limit: Optional[int] = None) -> List[EditTransaction]: """ Get transaction history. Args: limit: Maximum number of transactions to return Returns: List of transactions in reverse chronological order """ def rollback_transaction(self, transaction_id: Optional[str] = None) -> EditResult: """ Rollback to state before specified transaction. Args: transaction_id: Transaction to rollback (defaults to last) Returns: EditResult indicating rollback success Behavior: - Rolls back to document state before transaction - Removes rolled-back transactions from history - Validates document integrity after rollback """ def create_checkpoint(self, name: str, description: str = "") -> str: """ Create named checkpoint for manual rollback. Args: name: Checkpoint name description: Optional description Returns: Checkpoint identifier """ def rollback_to_checkpoint(self, checkpoint_id: str) -> EditResult: """Rollback to named checkpoint.""" ``` #### Document Export ```python def to_markdown(self) -> str: """Get current document as markdown string.""" def to_html(self) -> str: """Convert document to HTML.""" def to_json(self) -> str: """Export document structure as JSON.""" def get_statistics(self) -> DocumentStatistics: """Get comprehensive document statistics.""" ``` ### Validation and Analysis ```python def validate_document(self) -> List[ParseError]: """ Perform comprehensive document validation. Returns: List of validation errors and warnings Checks: - Heading hierarchy consistency - Link integrity - Markdown syntax validity - Document structure coherence """ def analyze_structure(self) -> StructureAnalysis: """ Analyze document structure and provide insights. Returns: StructureAnalysis with metrics and recommendations """ def find_broken_links(self) -> List[LinkError]: """Find broken internal and external links.""" def get_word_count(self, sections: Optional[List[SectionReference]] = None) -> int: """Get word count for entire document or specific sections.""" ``` ## Operation Semantics ### Atomicity Guarantees All operations in the SafeMarkdownEditor API are **strictly atomic**: 1. **Success State**: Operation completes fully, document is in valid state 2. **Failure State**: Operation rolls back completely, document unchanged 3. **No Partial States**: Never leaves document in inconsistent intermediate state ### Section Identification Stability Section references remain stable across most operations: - **Stable Across**: Content updates, section moves, level changes - **Invalidated By**: Section deletion, major structural changes - **Refresh Strategy**: Call `get_sections()` after structural changes ### Validation Levels ```python class ValidationLevel(Enum): STRICT = "strict" # Full validation, strict compliance NORMAL = "normal" # Standard validation, some flexibility PERMISSIVE = "permissive" # Minimal validation, maximum flexibility ``` **STRICT Mode:** - Enforces perfect heading hierarchy (no level skipping) - Validates all links and references - Requires valid markdown syntax throughout - Prevents any structural inconsistencies **NORMAL Mode** (Default): - Allows minor heading hierarchy issues (with warnings) - Validates critical structural elements - Permits some markdown syntax flexibility - Balances safety with usability **PERMISSIVE Mode:** - Minimal structural validation - Allows heading level jumps - Tolerates markdown syntax variations - Prioritizes operation success over strict compliance ## Error Handling ### Error Categories 1. **ValidationError**: Document structure or content validation failures 2. **OperationError**: Operation-specific failures (e.g., section not found) 3. **ParseError**: Markdown parsing failures 4. **ConcurrencyError**: Thread safety violations 5. **SystemError**: Underlying system or library failures ### Error Context All errors include: ```python @dataclass class ParseError: message: str # Human-readable error description error_code: str # Machine-readable error code line_number: Optional[int] # Line number where error occurred column_number: Optional[int] # Column number (if available) context: Optional[str] # Surrounding content for context suggestions: List[str] # Actionable suggestions for resolution severity: ErrorLevel # ERROR, WARNING, INFO category: ErrorCategory # Categorization for handling ``` ### Error Recovery Patterns ```python # Pattern 1: Simple error checking result = editor.update_section_content(section, new_content) if not result.success: print(f"Operation failed: {result.get_error_summary()}") return # Pattern 2: Detailed error handling result = editor.insert_section_after(section, 2, "New Section", content) if result.has_errors: for error in result.errors: if error.category == ErrorCategory.VALIDATION: print(f"Validation error: {error.message}") for suggestion in error.suggestions: print(f" Suggestion: {suggestion}") elif error.category == ErrorCategory.STRUCTURE: print(f"Structure error at line {error.line_number}: {error.message}") # Pattern 3: Preview-first error prevention preview = editor.preview_operation(EditOperation.DELETE_SECTION, section_ref=section, cascade_children=True) if preview.has_errors: print("Operation would fail:", preview.errors) else: result = editor.delete_section(section, cascade_children=True) ``` ## Thread Safety ### Concurrency Model The SafeMarkdownEditor uses a **multi-reader, single-writer** concurrency model: - **Read Operations**: Multiple threads can safely read simultaneously - **Write Operations**: Exclusive access required, automatic synchronization - **Transaction Isolation**: Each transaction has isolated workspace ### Thread Safety Guarantees ```python # Safe concurrent usage example import threading editor = SafeMarkdownEditor(markdown_text) def worker_thread(thread_id: int): # Safe: Multiple threads can read concurrently sections = editor.get_sections() stats = editor.get_statistics() # Safe: Writes are automatically synchronized result = editor.update_section_content( sections[thread_id % len(sections)], f"Updated by thread {thread_id}" ) # Start multiple worker threads threads = [threading.Thread(target=worker_thread, args=(i,)) for i in range(5)] for thread in threads: thread.start() for thread in threads: thread.join() ``` ### Deadlock Prevention - **Lock Ordering**: Consistent lock acquisition order - **Timeout Mechanisms**: Automatic timeout for lock acquisition - **Deadlock Detection**: Runtime detection and recovery ## Performance Characteristics ### Time Complexity | Operation | Best Case | Average Case | Worst Case | |-----------|-----------|--------------|------------| | `get_sections()` | O(h) | O(h) | O(h) | | `update_section_content()` | O(1) | O(n) | O(n) | | `insert_section_after()` | O(1) | O(n) | O(n) | | `delete_section()` | O(1) | O(n) | O(n) | | `move_section()` | O(1) | O(n) | O(n) | | `validate_document()` | O(n) | O(n) | O(n²) | Where: - `h` = number of headings - `n` = document size (lines or tokens) ### Memory Usage - **Base Memory**: O(n) for document storage - **Transaction History**: O(t×n) where t = number of transactions - **Section References**: O(h) for heading metadata - **Temporary Buffers**: O(n) during operations ### Optimization Strategies 1. **Lazy Validation**: Validation only when necessary 2. **Incremental Updates**: Minimize document reconstruction 3. **Reference Caching**: Cache section references between operations 4. **Transaction Compression**: Compress old transaction data ## Usage Examples ### Basic Document Editing ```python from quantalogic_markdown_mcp import SafeMarkdownEditor, EditOperation # Initialize editor markdown_text = """# Project Documentation ## Introduction This is the introduction. ## Getting Started Installation instructions here. ### Prerequisites List of requirements. """ editor = SafeMarkdownEditor(markdown_text) # Get document structure sections = editor.get_sections() print(f"Document has {len(sections)} sections") # Update section content intro_section = sections[1] # "Introduction" section result = editor.update_section_content( intro_section, "This is the **updated** introduction with more details." ) if result.success: print("Introduction updated successfully") else: print(f"Update failed: {result.get_error_summary()}") ``` ### Preview-Driven Editing ```python # Preview changes before applying preview = editor.preview_operation( EditOperation.INSERT_SECTION, after_section=sections[2], # After "Getting Started" level=2, title="Configuration", content="Configuration options and examples." ) if preview.success: print("Preview:") print(preview.preview[:200] + "...") # Apply the change result = editor.insert_section_after( sections[2], 2, "Configuration", "Configuration options and examples." ) print(f"Section added: {result.success}") else: print("Operation would fail:", preview.errors) ``` ### Atomic Batch Operations ```python # Execute multiple operations atomically operations = [ { 'operation': EditOperation.UPDATE_SECTION, 'section_ref': sections[0], 'content': 'Updated project overview' }, { 'operation': EditOperation.INSERT_SECTION, 'after_section': sections[-1], 'level': 2, 'title': 'Conclusion', 'content': 'Summary and next steps.' }, { 'operation': EditOperation.CHANGE_HEADING_LEVEL, 'section_ref': sections[3], # "Prerequisites" 'new_level': 2, 'cascade_children': True } ] result = editor.execute_batch_operations(operations) if result.success: print(f"Batch operation completed, {len(result.modified_sections)} sections modified") else: print("Batch operation failed, rolling back...") ``` ### Error Handling and Recovery ```python # Comprehensive error handling result = editor.delete_section(sections[1], cascade_children=True) if result.has_errors: print("Errors encountered:") for error in result.errors: print(f" {error.severity.value}: {error.message}") if error.line_number: print(f" At line {error.line_number}") for suggestion in error.suggestions: print(f" Suggestion: {suggestion}") if result.has_warnings: print("Warnings:") for warning in result.warnings: print(f" {warning.message}") # Rollback if needed if result.success: print("Section deleted successfully") else: print("Operation failed, document unchanged") # Manual rollback to previous state history = editor.get_transaction_history(limit=1) if history: rollback_result = editor.rollback_transaction() print(f"Rollback successful: {rollback_result.success}") ``` ### Advanced Structure Analysis ```python # Document analysis and validation validation_errors = editor.validate_document() if validation_errors: print("Document issues found:") for error in validation_errors: print(f" {error}") # Structure analysis analysis = editor.analyze_structure() print(f"Document depth: {analysis.max_heading_depth}") print(f"Section balance: {analysis.section_balance_score}") # Statistics stats = editor.get_statistics() print(f"Total sections: {stats.total_sections}") print(f"Word count: {stats.word_count}") print(f"Edit history: {stats.edit_count} transactions") ``` ## Migration Guide ### From Legacy MarkdownEditor The legacy `MarkdownEditor` API is deprecated but supported through a compatibility layer: ```python # OLD: Unsafe legacy API editor = MarkdownEditor(markdown_text) sections = editor.get_sections() # Returns dict objects editor.update_section_content("section_0", content) # String ID # NEW: Safe modern API editor = SafeMarkdownEditor(markdown_text) sections = editor.get_sections() # Returns SectionReference objects result = editor.update_section_content(sections[0], content) # Immutable reference ``` ### Migration Checklist 1. **Replace Constructor**: ```python # Before editor = MarkdownEditor(text) # After editor = SafeMarkdownEditor(text) ``` 2. **Update Section References**: ```python # Before sections = editor.get_sections() section_id = sections[0]['id'] # String ID # After sections = editor.get_sections() section_ref = sections[0] # SectionReference object ``` 3. **Handle Return Values**: ```python # Before result = editor.update_section_content(section_id, content) # result is ParseResult # After result = editor.update_section_content(section_ref, content) if result.success: # Handle success else: # Handle errors: result.errors ``` 4. **Add Error Handling**: ```python # Before editor.add_section(after_id, level, title, content) # No error checking # After result = editor.insert_section_after(after_ref, level, title, content) if not result.success: print(f"Failed: {result.get_error_summary()}") ``` ### Automated Migration Tools A migration script is provided to automatically convert legacy usage: ```bash python -m quantalogic_markdown_mcp.migrate --input legacy_code.py --output safe_code.py ``` ## Implementation Notes ### Internal Architecture ```text SafeMarkdownEditor ├── DocumentState (immutable snapshot) ├── TransactionManager (rollback support) ├── ValidationEngine (document integrity) ├── ConcurrencyController (thread safety) └── OperationExecutor (atomic operations) ``` ### Extension Points The API supports extension through: 1. **Custom Validators**: Add domain-specific validation rules 2. **Operation Plugins**: Implement custom editing operations 3. **Export Formats**: Add new output formats 4. **Analysis Tools**: Custom document analysis functions ### Testing Strategy The API includes comprehensive test coverage: - **Unit Tests**: Individual operation testing - **Integration Tests**: Multi-operation scenarios - **Concurrency Tests**: Thread safety validation - **Performance Tests**: Scalability benchmarks - **Regression Tests**: Backward compatibility ### Dependencies - `quantalogic-markdown-mcp >= 0.1.0`: Core parsing infrastructure - `markdown-it-py >= 3.0.0`: Markdown parsing engine - `typing-extensions >= 4.0.0`: Enhanced type annotations --- *This specification represents the definitive API contract for SafeMarkdownEditor v2.0.0. All implementations must conform to the behaviors and guarantees described in this document.*

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/quantalogic/quantalogic_markdown_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server