#!/usr/bin/env python3 """ Generates llms-full.txt by concatenating all documentation markdown files. This file is used by LLMs to understand the full documentation. Usage: generate-llms-full (after installing hindsight-dev) Output: hindsight-docs/static/llms-full.txt (served at /llms-full.txt) """ import re from datetime import datetime, timezone from pathlib import Path # Order matters - more important docs first DOC_ORDER = [ "developer/index.md", "developer/api/quickstart.md", "developer/api/main-methods.md", "developer/retain.md", "developer/retrieval.md", "developer/reflect.md", "developer/api/retain.md", "developer/api/recall.md", "developer/api/reflect.md", "developer/api/memory-banks.md", "developer/api/entities.md", "developer/api/documents.md", "developer/api/operations.md", "developer/installation.md", "developer/configuration.md", "developer/models.md", "developer/rag-vs-hindsight.md", "sdks/python.md", "sdks/nodejs.md", "sdks/cli.md", "sdks/mcp.md", "cookbook/index.mdx", "cookbook/recipes/quickstart.md", "cookbook/recipes/per-user-memory.md", "cookbook/recipes/support-agent-shared-knowledge.md", "cookbook/applications/openai-fitness-coach.md", ] def get_docs_dir() -> Path: """Find the hindsight-docs directory relative to this script.""" script_dir = Path(__file__).parent return script_dir.parent.parent / "hindsight-docs" / "docs" def get_output_file() -> Path: """Get output file path.""" script_dir = Path(__file__).parent return script_dir.parent.parent / "hindsight-docs" / "static" / "llms-full.txt" def get_all_markdown_files(docs_dir: Path) -> list[str]: """Recursively find all markdown files.""" files = [] for path in docs_dir.rglob("*"): if path.suffix in (".md", ".mdx"): files.append(str(path.relative_to(docs_dir))) return files def strip_frontmatter(content: str) -> str: """Remove YAML frontmatter (between --- markers).""" return re.sub(r"^---\n[\s\S]*?\n---\n", "", content) def clean_markdown(content: str) -> str: """Clean markdown content for LLM consumption.""" cleaned = strip_frontmatter(content) # Remove import statements cleaned = re.sub(r"^import\s+.*$", "", cleaned, flags=re.MULTILINE) # Remove JSX components (like ) cleaned = re.sub(r"<[A-Z][a-zA-Z]*\s+[^>]*/>", "", cleaned) cleaned = re.sub(r"<[A-Z][a-zA-Z]*[^>]*>[\s\S]*?", "", cleaned) # Remove empty lines at start cleaned = re.sub(r"^\n+", "", cleaned) return cleaned def main(): """Generate llms-full.txt.""" print("Generating llms-full.txt...") docs_dir = get_docs_dir() output_file = get_output_file() # Get all markdown files all_files = get_all_markdown_files(docs_dir) # Create ordered list: prioritized files first, then remaining files ordered_files = [] remaining_files = set(all_files) # Add prioritized files in order for file in DOC_ORDER: if file in remaining_files: ordered_files.append(file) remaining_files.discard(file) # Add remaining files (sorted alphabetically) ordered_files.extend(sorted(remaining_files)) # Build the output sections = [] # Header timestamp = datetime.now(timezone.utc).isoformat() sections.append(f"""# Hindsight Documentation > Agent Memory that Works Like Human Memory This file contains the complete Hindsight documentation for LLM consumption. Generated: {timestamp} --- """) # Process each file for file in ordered_files: file_path = docs_dir / file if not file_path.exists(): print(f" Warning: {file} not found, skipping") continue content = file_path.read_text() cleaned_content = clean_markdown(content) if cleaned_content.strip(): sections.append(f"\n## File: {file}\n") sections.append(cleaned_content) sections.append("\n---\n") print(f" Added: {file}") # Write output output = "\n".join(sections) output_file.write_text(output) size_kb = output_file.stat().st_size / 1024 print(f"\nGenerated: {output_file}") print(f"Size: {size_kb:.1f} KB") print(f"Files included: {len(ordered_files)}") if __name__ == "__main__": main()