Skip to main content
Glama
models.py5.37 kB
"""Data models for the knowledge base.""" from dataclasses import dataclass, field from datetime import datetime from typing import Any, Optional, List @dataclass class NoteFrontmatter: """Represents the YAML frontmatter of a note.""" tags: list[str] = field(default_factory=list) date: str = field(default_factory=lambda: datetime.now().strftime("%Y-%m-%d")) category: str = "" updated: Optional[str] = None metadata: dict[str, Any] = field(default_factory=dict) # For category-specific fields def to_dict(self) -> dict[str, Any]: """Convert frontmatter to dictionary for YAML serialization.""" result = { "tags": self.tags, "date": self.date, "category": self.category, } if self.updated: result["updated"] = self.updated # Add any additional metadata fields result.update(self.metadata) return result @classmethod def from_dict(cls, data: dict[str, Any]) -> "NoteFrontmatter": """Create frontmatter from dictionary.""" tags = data.get("tags", []) date = data.get("date", datetime.now().strftime("%Y-%m-%d")) category = data.get("category", "") updated = data.get("updated") # Extract metadata (everything else) metadata = { k: v for k, v in data.items() if k not in {"tags", "date", "category", "updated"} } return cls( tags=tags if isinstance(tags, list) else [], date=date, category=category, updated=updated, metadata=metadata ) @dataclass class Note: """Represents a complete note with frontmatter and content.""" title: str category: str frontmatter: NoteFrontmatter content: str file_path: str = "" def get_preview(self, length: int = 150) -> str: """Get a preview of the note content.""" # Remove markdown headers and extra whitespace preview = self.content.strip() lines = [line.strip() for line in preview.split('\n') if line.strip() and not line.startswith('#')] preview = ' '.join(lines) if len(preview) > length: return preview[:length] + "..." return preview def __str__(self) -> str: """String representation of the note.""" tags_str = ', '.join(self.frontmatter.tags) if self.frontmatter.tags else 'no tags' return f"[{self.category}] {self.title} [{tags_str}]" @dataclass class SearchResult: """Represents a search result.""" note: Note relevance_score: float = 0.0 def __str__(self) -> str: """Format search result for display.""" preview = self.note.get_preview() tags_str = ', '.join(self.note.frontmatter.tags) if self.note.frontmatter.tags else 'no tags' return f"[{self.note.category}] {self.note.title} [{tags_str}]\n {preview}" @dataclass class CategoryMetadata: """Metadata for a category.""" description: Optional[str] = None created: str = field(default_factory=lambda: datetime.now().strftime("%Y-%m-%d")) custom_fields: dict[str, Any] = field(default_factory=dict) def to_dict(self) -> dict[str, Any]: """Convert to dictionary for JSON serialization.""" result = {"created": self.created} if self.description: result["description"] = self.description result.update(self.custom_fields) return result @classmethod def from_dict(cls, data: dict[str, Any]) -> "CategoryMetadata": """Create from dictionary.""" description = data.get("description") created = data.get("created", datetime.now().strftime("%Y-%m-%d")) custom_fields = { k: v for k, v in data.items() if k not in {"description", "created"} } return cls( description=description, created=created, custom_fields=custom_fields ) @dataclass class CategoryInfo: """Information about a category in the hierarchical structure.""" name: str path: str note_count: int = 0 depth: int = 0 children: List["CategoryInfo"] = field(default_factory=list) metadata: Optional[CategoryMetadata] = None def to_dict(self) -> dict[str, Any]: """Convert to dictionary for JSON serialization.""" return { "name": self.name, "path": self.path, "note_count": self.note_count, "depth": self.depth, "children": [child.to_dict() for child in self.children], "metadata": self.metadata.to_dict() if self.metadata else None } def format_tree(self, indent: int = 0, show_counts: bool = True) -> str: """ Format category as indented tree structure. Args: indent: Current indentation level show_counts: Whether to show note counts Returns: Formatted string representation """ indent_str = " " * indent count_str = f" ({self.note_count} notes)" if show_counts else "" result = f"{indent_str}{self.name}/{count_str}\n" for child in sorted(self.children, key=lambda c: c.name): result += child.format_tree(indent + 1, show_counts) return result

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/cwente25/KnowledgeBaseMCP'

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