1+ import streamlit as st
2+ import os
3+ import dotenv
4+ from flow import create_tutorial_flow
5+
6+ # Load environment variables
7+ dotenv .load_dotenv ()
8+
9+ # Default file patterns
10+ DEFAULT_INCLUDE_PATTERNS = {
11+ "*.py" , "*.js" , "*.ts" , "*.go" , "*.java" , "*.pyi" , "*.pyx" ,
12+ "*.c" , "*.cc" , "*.cpp" , "*.h" , "*.md" , "*.rst" , "Dockerfile" ,
13+ "Makefile" , "*.yaml" , "*.yml"
14+ }
15+
16+ DEFAULT_EXCLUDE_PATTERNS = {
17+ "*test*" , "tests/*" , "docs/*" , "examples/*" , "v1/*" ,
18+ "dist/*" , "build/*" , "experimental/*" , "deprecated/*" ,
19+ "legacy/*" , ".git/*" , ".github/*"
20+ }
21+
22+ # Set page config
23+ st .set_page_config (
24+ page_title = "Codebase Tutorial Generator" ,
25+ page_icon = "📚" ,
26+ layout = "wide"
27+ )
28+
29+ # Title and description
30+ st .title ("📚 Codebase Tutorial Generator" )
31+ st .markdown ("""
32+ This app generates comprehensive tutorials for GitHub codebases using AI.
33+ Simply provide a GitHub repository URL and customize the generation settings.
34+ """ )
35+
36+ # Sidebar for configuration
37+ with st .sidebar :
38+ st .header ("Configuration" )
39+
40+ # GitHub token input
41+ github_token = st .text_input (
42+ "GitHub Token (optional)" ,
43+ value = os .environ .get ("GITHUB_TOKEN" , "" ),
44+ type = "password" ,
45+ help = "Personal access token for GitHub API. Helps avoid rate limits."
46+ )
47+
48+ # Output directory
49+ output_dir = st .text_input (
50+ "Output Directory" ,
51+ value = "output" ,
52+ help = "Directory where the tutorial will be saved"
53+ )
54+
55+ # Advanced options
56+ with st .expander ("Advanced Options" ):
57+ # File size limit
58+ max_file_size = st .number_input (
59+ "Max File Size (bytes)" ,
60+ value = 100000 ,
61+ min_value = 1000 ,
62+ help = "Maximum file size to process (in bytes)"
63+ )
64+
65+ # Include patterns
66+ include_patterns_str = st .text_area (
67+ "Include Patterns" ,
68+ value = "\n " .join (DEFAULT_INCLUDE_PATTERNS ),
69+ help = "File patterns to include (one per line)"
70+ )
71+
72+ # Exclude patterns
73+ exclude_patterns_str = st .text_area (
74+ "Exclude Patterns" ,
75+ value = "\n " .join (DEFAULT_EXCLUDE_PATTERNS ),
76+ help = "File patterns to exclude (one per line)"
77+ )
78+
79+ # Main form
80+ with st .form ("tutorial_form" ):
81+ # Repository URL
82+ repo_url = st .text_input (
83+ "GitHub Repository URL" ,
84+ placeholder = "https://github.com/username/repository" ,
85+ help = "URL of the public GitHub repository"
86+ )
87+
88+ # Project name (optional)
89+ project_name = st .text_input (
90+ "Project Name (optional)" ,
91+ help = "Custom name for the project (derived from URL if omitted)"
92+ )
93+
94+ # Submit button
95+ submit_button = st .form_submit_button ("Generate Tutorial" )
96+
97+ # Process form submission
98+ if submit_button :
99+ if not repo_url :
100+ st .error ("Please enter a GitHub repository URL" )
101+ else :
102+ # Show progress
103+ progress_bar = st .progress (0 )
104+ status_text = st .empty ()
105+
106+ # Parse include/exclude patterns
107+ include_patterns = set (filter (None , include_patterns_str .split ("\n " )))
108+ exclude_patterns = set (filter (None , exclude_patterns_str .split ("\n " )))
109+
110+ # Initialize shared dictionary
111+ shared = {
112+ "repo_url" : repo_url ,
113+ "project_name" : project_name if project_name else None ,
114+ "github_token" : github_token if github_token else os .environ .get ("GITHUB_TOKEN" ),
115+ "output_dir" : output_dir ,
116+ "include_patterns" : include_patterns ,
117+ "exclude_patterns" : exclude_patterns ,
118+ "max_file_size" : max_file_size ,
119+ "files" : [],
120+ "abstractions" : [],
121+ "relationships" : {},
122+ "chapter_order" : [],
123+ "chapters" : [],
124+ "final_output_dir" : None
125+ }
126+
127+ try :
128+ # Create and run the flow
129+ status_text .text ("Starting tutorial generation..." )
130+ progress_bar .progress (10 )
131+
132+ tutorial_flow = create_tutorial_flow ()
133+
134+ # Update status for each node
135+ status_text .text ("Fetching repository..." )
136+ progress_bar .progress (20 )
137+
138+ # Run the flow with progress updates
139+ # Note: In a real implementation, you would need to modify the flow
140+ # to provide progress updates or use callbacks
141+ result = tutorial_flow .run (shared )
142+
143+ progress_bar .progress (100 )
144+ status_text .text ("Tutorial generation complete!" )
145+
146+ # Display result
147+ if result .get ("final_output_dir" ):
148+ st .success (f"Tutorial generated successfully in: { result ['final_output_dir' ]} " )
149+
150+ # Provide download links if files are accessible
151+ st .markdown ("### Download Tutorial Files" )
152+ for file in os .listdir (result ["final_output_dir" ]):
153+ file_path = os .path .join (result ["final_output_dir" ], file )
154+ if os .path .isfile (file_path ):
155+ with open (file_path , "rb" ) as f :
156+ st .download_button (
157+ label = f"Download { file } " ,
158+ data = f ,
159+ file_name = file ,
160+ mime = "text/markdown"
161+ )
162+ else :
163+ st .warning ("Tutorial generation completed but output directory not found." )
164+
165+ except Exception as e :
166+ st .error (f"Error generating tutorial: { str (e )} " )
167+ st .exception (e )
168+
169+ # Display information about the app
170+ st .markdown ("---" )
171+ st .markdown ("""
172+ ### How it works
173+ 1. The app clones the GitHub repository
174+ 2. It analyzes the codebase structure and identifies key abstractions
175+ 3. It determines relationships between components
176+ 4. It generates tutorial chapters in a logical order
177+ 5. Finally, it combines everything into a comprehensive tutorial
178+
179+ ### Requirements
180+ - A public GitHub repository
181+ - Google Gemini API access (configured via environment variables)
182+ """ )
0 commit comments