File size: 11,299 Bytes
e6ff539
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
import os
import streamlit as st
import pyperclip
import yaml
from datetime import datetime

# Function to format date
def format_date(timestamp):
    return datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")

# Function to convert folder names to readable format
def format_folder_name(folder_name):
    return folder_name.replace("-", " ").title()

# Function to load markdown files and extract YAML front matter and content
def load_markdown(file_path):
    with open(file_path, 'r') as file:
        content = file.read()
    
    # Check for YAML front matter
    if content.startswith('---'):
        parts = content.split('---', 2)
        if len(parts) >= 3:
            yaml_content = parts[1].strip()
            markdown_content = parts[2].strip()
            try:
                front_matter = yaml.safe_load(yaml_content)
                # Ensure tags is a list
                if 'tags' in front_matter:
                    if isinstance(front_matter['tags'], str):
                        front_matter['tags'] = [tag.strip() for tag in front_matter['tags'].split(',')]
                else:
                    front_matter['tags'] = []
                return front_matter, markdown_content
            except yaml.YAMLError:
                return {'tags': []}, content
    return {'tags': []}, content

# Function to extract the first header from markdown content
def extract_title_and_body(markdown_content):
    lines = markdown_content.split('\n')
    title = "Untitled Configuration"
    body = markdown_content
    
    for i, line in enumerate(lines):
        if line.startswith('# '):
            title = line.strip('# ').strip()
            body = '\n'.join(lines[i+1:]).strip()
            break
    
    return title, body

# Function to recursively build the sidebar navigation
def build_sidebar_navigation(base_path, current_path):
    items = os.listdir(current_path)
    for item in sorted(items):
        item_path = os.path.join(current_path, item)
        if os.path.isdir(item_path):
            with st.sidebar.expander(format_folder_name(item)):
                build_sidebar_navigation(base_path, item_path)
        elif item.endswith('.md'):
            front_matter, markdown_content = load_markdown(item_path)
            title, _ = extract_title_and_body(markdown_content)
            # Add binoculars icon if vision is enabled
            vision = front_matter.get("vision", "")
            vision_icon = " πŸ”­" if str(vision).lower() == "yes" else ""
            if st.sidebar.button(f"{title}{vision_icon}", key=item_path):
                st.session_state['selected_file'] = item_path

# Function to search for configurations
def search_configurations(base_path, search_term, selected_tags=None):
    matches = []
    for root, dirs, files in os.walk(base_path):
        for file in files:
            if file.endswith('.md'):
                file_path = os.path.join(root, file)
                front_matter, markdown_content = load_markdown(file_path)
                title, body = extract_title_and_body(markdown_content)
                
                # Check if content matches search term and tags
                content_matches = search_term.lower() in markdown_content.lower()
                tags_match = True
                if selected_tags:
                    tags_match = any(tag in front_matter.get('tags', []) for tag in selected_tags)
                
                if content_matches and tags_match:
                    matches.append((file_path, title, front_matter.get('tags', [])))
    return matches

# Main function to run the Streamlit app
def main():
    st.set_page_config(page_title="AI Agent Configurations", layout="wide")

    # Define the base path for agent configurations
    base_path = "agent-configs"

    # Initialize session state
    if 'selected_file' not in st.session_state:
        st.session_state['selected_file'] = None
    if 'dark_mode' not in st.session_state:
        st.session_state['dark_mode'] = False
    if 'favorites' not in st.session_state:
        st.session_state['favorites'] = set()

    # Apply dark mode if enabled
    if st.session_state['dark_mode']:
        st.markdown("""
            <style>
            .stApp {
                background-color: #1E1E1E;
                color: #FFFFFF;
            }
            .sidebar .sidebar-content {
                background-color: #2D2D2D;
            }
            </style>
            """, unsafe_allow_html=True)

    # Sidebar for navigation and search
    st.sidebar.title("AI Agent Configurations")
    
    # Dark mode toggle
    st.sidebar.checkbox("Dark Mode", key="dark_mode", value=st.session_state['dark_mode'])
    
    # GitHub repository badge in sidebar
    st.sidebar.markdown(
        "[![View on GitHub](https://img.shields.io/badge/View_on_GitHub-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/danielrosehill/LLM-Assistants-Web-Library)",
        unsafe_allow_html=True
    )
    
    # Collect all configurations and their metadata
    all_configs = []
    all_tags = set()
    for root, _, files in os.walk(base_path):
        for file in files:
            if file.endswith('.md'):
                file_path = os.path.join(root, file)
                front_matter, _ = load_markdown(file_path)
                title, _ = extract_title_and_body(_)
                last_modified = os.path.getmtime(file_path)
                all_configs.append({
                    'path': file_path,
                    'title': title,
                    'tags': front_matter.get('tags', []),
                    'last_modified': last_modified
                })
                all_tags.update(front_matter.get('tags', []))
    
    # Sorting options
    sort_options = {
        'Title (A-Z)': lambda x: x['title'].lower(),
        'Title (Z-A)': lambda x: x['title'].lower(),
        'Last Modified (Newest)': lambda x: x['last_modified'],
        'Last Modified (Oldest)': lambda x: x['last_modified']
    }
    sort_by = st.sidebar.selectbox('Sort by', list(sort_options.keys()))
    
    # Sort configurations
    all_configs.sort(key=sort_options[sort_by])
    if sort_by == 'Title (Z-A)' or sort_by == 'Last Modified (Newest)':
        all_configs.reverse()
    
    # Search and filter functionality
    search_term = st.sidebar.text_input("Search configurations")
    selected_tags = st.sidebar.multiselect("Filter by tags", sorted(list(all_tags)))
    
    # Show favorites section if there are any
    if st.session_state['favorites']:
        st.sidebar.markdown("### Favorites")
        for file_path in st.session_state['favorites']:
            front_matter, _ = load_markdown(file_path)
            title, _ = extract_title_and_body(_)
            if st.sidebar.button(f"⭐ {title}", key=f"fav_{file_path}"):
                st.session_state['selected_file'] = file_path
        st.sidebar.divider()
    
    if search_term or selected_tags:
        matches = search_configurations(base_path, search_term, selected_tags)
        if matches:
            st.sidebar.write("Search Results:")
            for file_path, title, tags in matches:
                if st.sidebar.button(f"{title} ({', '.join(tags)})", key=f"search_{file_path}"):
                    st.session_state['selected_file'] = file_path
        else:
            st.sidebar.write("No matches found.")
    else:
        # Build the sidebar navigation
        build_sidebar_navigation(base_path, base_path)

    # Main content area
    st.title("Daniel Rosehill AI Assistant Library")
    st.markdown(
        """
        <div style="background-color: #f0f0f0; padding: 10px; border-radius: 10px; margin-bottom: 20px;">
            <p style="margin: 0;">This microsite contains open source configurations for AI assistants.</p>
        </div>
        """,
        unsafe_allow_html=True
    )

    if st.session_state['selected_file']:
        front_matter, markdown_content = load_markdown(st.session_state['selected_file'])
        title, body = extract_title_and_body(markdown_content)
        
        # Display title and metadata
        st.markdown(f"# {title}")
        
        # Display tags if present
        if front_matter.get('tags'):
            st.markdown("**Tags:** " + ", ".join(f"`{tag}`" for tag in front_matter['tags']))
        
        # Display last modified date
        last_modified = os.path.getmtime(st.session_state['selected_file'])
        st.markdown(f"**Last Modified:** {format_date(last_modified)}")
        
        # Create a container for buttons
        with st.container():
            st.write("Options:")
            button_col1, button_col2, button_col3, button_col4, _ = st.columns([2, 2, 2, 2, 4])
            
            with button_col1:
                if st.button("πŸ“‹ Copy Title", 
                           key="copy_title",
                           help="Copy title to clipboard",
                           type="secondary"):
                    pyperclip.copy(title)
                    st.success("Title copied!")
            
            with button_col2:
                if st.button("πŸ“„ Copy Content", 
                           key="copy_body",
                           help="Copy full content to clipboard",
                           type="secondary"):
                    pyperclip.copy(body)
                    st.success("Content copied!")
            
            with button_col3:
                is_favorite = st.session_state['selected_file'] in st.session_state['favorites']
                if st.button("⭐ " + ("Unfavorite" if is_favorite else "Favorite"),
                           key="toggle_favorite",
                           help="Add/remove from favorites",
                           type="secondary"):
                    if is_favorite:
                        st.session_state['favorites'].remove(st.session_state['selected_file'])
                    else:
                        st.session_state['favorites'].add(st.session_state['selected_file'])
            
            with button_col4:
                if st.button("πŸ”— Share",
                           key="share_config",
                           help="Copy shareable link",
                           type="secondary"):
                    share_url = f"https://github.com/danielrosehill/LLM-Assistants-Web-Library/blob/main/{st.session_state['selected_file']}"
                    pyperclip.copy(share_url)
                    st.success("Share link copied!")
        
        st.divider()
        
        # Display markdown content
        st.markdown(body, unsafe_allow_html=True)
    else:
        st.write("Select a configuration from the sidebar to view its details.")
    
    # Footer with GitHub badge
    st.markdown(
        """
        <div style="position: fixed; bottom: 0; width: 100%; background-color: #f0f0f0; padding: 10px; text-align: center;">
            <a href="https://github.com/danielrosehill/LLM-Assistants-Web-Library" target="_blank">
                <img src="https://img.shields.io/badge/View_on_GitHub-181717?style=for-the-badge&logo=github&logoColor=white" alt="View on GitHub">
            </a>
        </div>
        """,
        unsafe_allow_html=True
    )

if __name__ == "__main__":
    main()