awacke1 commited on
Commit
445b0aa
Β·
verified Β·
1 Parent(s): ff2cad3

Create backup11.app.py

Browse files
Files changed (1) hide show
  1. backup11.app.py +1049 -0
backup11.app.py ADDED
@@ -0,0 +1,1049 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Import libraries and references:
2
+ import anthropic
3
+ import base64
4
+ import glob
5
+ import hashlib
6
+ import json
7
+ import os
8
+ import pandas as pd
9
+ import pytz
10
+ import random
11
+ import re
12
+ import shutil
13
+ import streamlit as st
14
+ import time
15
+ import traceback
16
+ import uuid
17
+ import zipfile
18
+ from PIL import Image
19
+ from azure.cosmos import CosmosClient, exceptions
20
+ from datetime import datetime
21
+ from git import Repo
22
+ from github import Github
23
+ from gradio_client import Client
24
+ from urllib.parse import quote
25
+
26
+
27
+ # 🎭 App Configuration - Because every app needs a good costume!
28
+ Site_Name = 'πŸ™GitCosmos🌌 - AI Azure Cosmos DB and Github Agent'
29
+ title = "πŸ™GitCosmos🌌 - AI Azure Cosmos DB and Github Agent"
30
+ helpURL = 'https://huggingface.co/awacke1'
31
+ bugURL = 'https://huggingface.co/spaces/awacke1/AzureCosmosDBUI/'
32
+ icons = 'πŸ™πŸŒŒπŸ’«'
33
+ st.set_page_config(
34
+ page_title=title,
35
+ page_icon=icons,
36
+ layout="wide",
37
+ initial_sidebar_state="auto",
38
+ menu_items={
39
+ 'Get Help': helpURL,
40
+ 'Report a bug': bugURL,
41
+ 'About': title
42
+ }
43
+ )
44
+
45
+
46
+ # 🌌 Cosmos DB configuration - Where data goes to party!
47
+ ENDPOINT = "https://acae-afd.documents.azure.com:443/"
48
+ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
49
+ CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
50
+ Key = os.environ.get("Key")
51
+
52
+ # 🌐 Your local app URL - Home sweet home
53
+ LOCAL_APP_URL = "https://huggingface.co/spaces/awacke1/AzureCosmosDBUI"
54
+ CosmosDBUrl = 'https://portal.azure.com/#@AaronCWackergmail.onmicrosoft.com/resource/subscriptions/003fba60-5b3f-48f4-ab36-3ed11bc40816/resourceGroups/datasets/providers/Microsoft.DocumentDB/databaseAccounts/acae-afd/dataExplorer'
55
+
56
+ # πŸ€– Anthropic configuration - Teaching machines to be more human (and funnier)
57
+ client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
58
+
59
+ # 🧠 Initialize session state - Because even apps need a good memory
60
+ if "chat_history" not in st.session_state:
61
+ st.session_state.chat_history = []
62
+
63
+
64
+
65
+ # πŸ› οΈ Helper Functions - The unsung heroes of our code
66
+
67
+ # πŸ“Ž Get a file download link - Making file sharing as easy as stealing candy from a baby
68
+ def get_download_link(file_path):
69
+ with open(file_path, "rb") as file:
70
+ contents = file.read()
71
+ b64 = base64.b64encode(contents).decode()
72
+ file_name = os.path.basename(file_path)
73
+ return f'<a href="data:file/txt;base64,{b64}" download="{file_name}">Download {file_name}πŸ“‚</a>'
74
+
75
+ # 🎲 Generate a unique ID - Because being unique is important (just ask your mother)
76
+ def generate_unique_id():
77
+ timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
78
+ unique_uuid = str(uuid.uuid4())
79
+ returnValue = f"{timestamp}-{unique_uuid}"
80
+ st.write('New Unique ID:' + returnValue)
81
+ return
82
+
83
+ # πŸ“ Generate a filename - Naming files like a pro (or a very confused librarian)
84
+ def generate_filename(prompt, file_type):
85
+ central = pytz.timezone('US/Central')
86
+ safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
87
+ safe_prompt = re.sub(r'\W+', '', prompt)[:90]
88
+ return f"{safe_date_time}{safe_prompt}.{file_type}"
89
+
90
+ # πŸ’Ύ Create and save a file - Because data hoarding is a legitimate hobby
91
+ def create_file(filename, prompt, response, should_save=True):
92
+ if not should_save:
93
+ return
94
+ with open(filename, 'w', encoding='utf-8') as file:
95
+ file.write(prompt + "\n\n" + response)
96
+
97
+ # πŸ“– Load file content - Bringing words back from the digital grave
98
+ def load_file(file_name):
99
+ with open(file_name, "r", encoding='utf-8') as file:
100
+ content = file.read()
101
+ return content
102
+
103
+ # πŸ” Display glossary entity - Making search fun again (as if it ever was)
104
+ def display_glossary_entity(k):
105
+ search_urls = {
106
+ "πŸš€πŸŒŒArXiv": lambda k: f"/?q={quote(k)}",
107
+ "πŸ“–": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
108
+ "πŸ”": lambda k: f"https://www.google.com/search?q={quote(k)}",
109
+ "πŸŽ₯": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
110
+ }
111
+ links_md = ' '.join([f"<a href='{url(k)}' target='_blank'>{emoji}</a>" for emoji, url in search_urls.items()])
112
+ st.markdown(f"{k} {links_md}", unsafe_allow_html=True)
113
+
114
+ # πŸ—œοΈ Create zip of files - Squeezing files together like sardines in a can
115
+ def create_zip_of_files(files):
116
+ zip_name = "all_files.zip"
117
+ with zipfile.ZipFile(zip_name, 'w') as zipf:
118
+ for file in files:
119
+ zipf.write(file)
120
+ return zip_name
121
+
122
+ # 🎬 Get video HTML - Making videos play nice (or at least trying to)
123
+ def get_video_html(video_path, width="100%"):
124
+ video_url = f"data:video/mp4;base64,{base64.b64encode(open(video_path, 'rb').read()).decode()}"
125
+ return f'''
126
+ <video width="{width}" controls autoplay loop>
127
+ <source src="{video_url}" type="video/mp4">
128
+ Your browser does not support the video tag.
129
+ </video>
130
+ '''
131
+
132
+ # 🎡 Get audio HTML - Let the music play (and hope it's not Baby Shark)
133
+ def get_audio_html(audio_path, width="100%"):
134
+ audio_url = f"data:audio/mpeg;base64,{base64.b64encode(open(audio_path, 'rb').read()).decode()}"
135
+ return f'''
136
+ <audio controls style="width:{width}">
137
+ <source src="{audio_url}" type="audio/mpeg">
138
+ Your browser does not support the audio element.
139
+ </audio>
140
+ '''
141
+
142
+ # 🌌 Cosmos DB functions - Where data goes to live its best life
143
+
144
+ # πŸ“š Get databases - Collecting databases like Pokemon cards
145
+ def get_databases(client):
146
+ return [db['id'] for db in client.list_databases()]
147
+
148
+ # πŸ“¦ Get containers - Finding where all the good stuff is hidden
149
+ def get_containers(database):
150
+ return [container['id'] for container in database.list_containers()]
151
+
152
+ # πŸ“„ Get documents - Retrieving the sacred texts (or just some JSON)
153
+ def get_documents(container, limit=None):
154
+ query = "SELECT * FROM c ORDER BY c._ts DESC"
155
+ items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
156
+ return items
157
+
158
+ # πŸ“₯ Insert record - Adding new data (and crossing fingers it doesn't break anything)
159
+ def insert_record(container, record):
160
+ try:
161
+ container.create_item(body=record)
162
+ return True, "Record inserted successfully! πŸŽ‰"
163
+ except exceptions.CosmosHttpResponseError as e:
164
+ return False, f"HTTP error occurred: {str(e)} 🚨"
165
+ except Exception as e:
166
+ return False, f"An unexpected error occurred: {str(e)} 😱"
167
+
168
+ # πŸ”„ Update record - Giving data a makeover
169
+ def update_record(container, updated_record):
170
+ try:
171
+ container.upsert_item(body=updated_record)
172
+ return True, f"Record with id {updated_record['id']} successfully updated. πŸ› οΈ"
173
+ except exceptions.CosmosHttpResponseError as e:
174
+ return False, f"HTTP error occurred: {str(e)} 🚨"
175
+ except Exception as e:
176
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
177
+
178
+ # πŸ—‘οΈ Delete record - Saying goodbye to data (it's not you, it's me)
179
+ def delete_record(container, record):
180
+ try:
181
+ container.delete_item(item=record['id'], partition_key=record['id'])
182
+ return True, f"Record with id {record['id']} successfully deleted. πŸ—‘οΈ"
183
+ except exceptions.CosmosHttpResponseError as e:
184
+ return False, f"HTTP error occurred: {str(e)} 🚨"
185
+ except Exception as e:
186
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
187
+
188
+
189
+ # πŸ’Ύ Save to Cosmos DB - Preserving data for future generations (or just until the next update)
190
+ def save_to_cosmos_db(container, query, response1, response2):
191
+ try:
192
+ if container:
193
+ record = {
194
+ "id": generate_unique_id(),
195
+ "query": query,
196
+ "response1": response1,
197
+ "response2": response2,
198
+ "timestamp": datetime.utcnow().isoformat()
199
+ }
200
+ try:
201
+ container.create_item(body=record)
202
+ st.success(f"Record saved successfully with ID: {record['id']}")
203
+ # Refresh the documents display
204
+ st.session_state.documents = get_documents(container)
205
+ except exceptions.CosmosHttpResponseError as e:
206
+ st.error(f"Error saving record to Cosmos DB: {e}")
207
+ else:
208
+ st.error("Cosmos DB container is not initialized.")
209
+ except Exception as e:
210
+ st.error(f"An unexpected error occurred: {str(e)}")
211
+
212
+
213
+
214
+ # πŸ™ GitHub functions - Where code goes to socialize
215
+
216
+ # πŸ“₯ Download GitHub repo - Cloning repos like it's going out of style
217
+ def download_github_repo(url, local_path):
218
+ if os.path.exists(local_path):
219
+ shutil.rmtree(local_path)
220
+ Repo.clone_from(url, local_path)
221
+
222
+ # πŸ—œοΈ Create zip file - Squeezing files tighter than your budget
223
+ def create_zip_file(source_dir, output_filename):
224
+ shutil.make_archive(output_filename, 'zip', source_dir)
225
+
226
+ # πŸ—οΈ Create repo - Building digital homes for lonely code
227
+ def create_repo(g, repo_name):
228
+ user = g.get_user()
229
+ return user.create_repo(repo_name)
230
+
231
+ # πŸš€ Push to GitHub - Sending code to the cloud (hopefully not the rainy kind)
232
+ def push_to_github(local_path, repo, github_token):
233
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
234
+ local_repo = Repo(local_path)
235
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
236
+ origin = local_repo.remote('origin')
237
+ origin.set_url(repo_url)
238
+ else:
239
+ origin = local_repo.create_remote('origin', repo_url)
240
+ if not local_repo.heads:
241
+ local_repo.git.checkout('-b', 'main')
242
+ current_branch = 'main'
243
+ else:
244
+ current_branch = local_repo.active_branch.name
245
+ local_repo.git.add(A=True)
246
+ if local_repo.is_dirty():
247
+ local_repo.git.commit('-m', 'Initial commit')
248
+ origin.push(refspec=f'{current_branch}:{current_branch}')
249
+
250
+
251
+ def save_or_clone_to_cosmos_db(container, document=None, clone_id=None):
252
+ def generate_complex_unique_id():
253
+ timestamp = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')
254
+ random_component = ''.join(random.choices('abcdefghijklmnopqrstuvwxyz0123456789', k=8))
255
+ return f"{timestamp}-{random_component}-{str(uuid.uuid4())}"
256
+ max_retries = 10
257
+ base_delay = 0.1
258
+ for attempt in range(max_retries):
259
+ try:
260
+ new_id = generate_complex_unique_id()
261
+ if clone_id:
262
+ try:
263
+ existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
264
+ new_doc = {
265
+ 'id': new_id,
266
+ 'originalText': existing_doc.get('originalText', ''),
267
+ 'qtPrompts': existing_doc.get('qtPrompts', []),
268
+ 'cloned_from': clone_id,
269
+ 'cloned_at': datetime.utcnow().isoformat()
270
+ }
271
+ except exceptions.CosmosResourceNotFoundError:
272
+ return False, f"Document with ID {clone_id} not found for cloning."
273
+ else:
274
+ if document is None:
275
+ return False, "No document provided for saving"
276
+ document['id'] = new_id
277
+ document['created_at'] = datetime.utcnow().isoformat()
278
+ new_doc = document
279
+ response = container.create_item(body=new_doc)
280
+ return True, f"{'Cloned' if clone_id else 'New'} document saved successfully with ID: {response['id']}"
281
+ except exceptions.CosmosHttpResponseError as e:
282
+ if e.status_code == 409:
283
+ delay = base_delay * (2 ** attempt) + random.uniform(0, 0.1)
284
+ time.sleep(delay)
285
+ continue
286
+ return False, f"Error saving to Cosmos DB: {str(e)}"
287
+ except Exception as e:
288
+ return False, f"An unexpected error occurred: {str(e)}"
289
+ return False, "Failed to save document after maximum retries."
290
+
291
+
292
+ # πŸ“¦ Archive current container - Packing up data like you're moving to a new digital house
293
+ def archive_current_container(database_name, container_name, client):
294
+ try:
295
+ base_dir = "./cosmos_archive_current_container"
296
+ if os.path.exists(base_dir):
297
+ shutil.rmtree(base_dir)
298
+ os.makedirs(base_dir)
299
+ db_client = client.get_database_client(database_name)
300
+ container_client = db_client.get_container_client(container_name)
301
+ items = list(container_client.read_all_items())
302
+ container_dir = os.path.join(base_dir, container_name)
303
+ os.makedirs(container_dir)
304
+ for item in items:
305
+ item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
306
+ with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
307
+ json.dump(item, f, indent=2)
308
+ archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
309
+ shutil.make_archive(archive_name, 'zip', base_dir)
310
+ return get_download_link(f"{archive_name}.zip")
311
+ except Exception as e:
312
+ return f"An error occurred while archiving data: {str(e)} 😒"
313
+
314
+
315
+ # πŸ” Search glossary - Finding needles in digital haystacks
316
+ def search_glossary(query):
317
+ st.markdown(f"### πŸ” SearchGlossary for: {query}")
318
+ # Dropdown for model selection
319
+ model_options = ['mistralai/Mixtral-8x7B-Instruct-v0.1', 'mistralai/Mistral-7B-Instruct-v0.2', 'google/gemma-7b-it', 'None']
320
+ #model_choice = st.selectbox('🧠 Select LLM Model', options=model_options, index=1)
321
+ # Dropdown for database selection
322
+ database_options = ['Semantic Search', 'Arxiv Search - Latest - (EXPERIMENTAL)']
323
+ #database_choice = st.selectbox('πŸ“š Select Database', options=database_options, index=0)
324
+ # πŸ•΅οΈβ€β™‚οΈ Searching the glossary for: query
325
+ all_results = ""
326
+ #st.markdown(f"- {query}")
327
+
328
+
329
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM
330
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
331
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
332
+ result = client.predict(
333
+ prompt=query,
334
+ llm_model_picked="mistralai/Mixtral-8x7B-Instruct-v0.1",
335
+ stream_outputs=True,
336
+ api_name="/ask_llm"
337
+ )
338
+ st.markdown("# Mixtral-8x7B-Instruct-v0.1")
339
+ st.markdown(result)
340
+ #st.code(result, language="python", line_numbers=True)
341
+
342
+
343
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /ask_llm
344
+ result2 = client.predict(
345
+ prompt=query,
346
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
347
+ stream_outputs=True,
348
+ api_name="/ask_llm"
349
+ )
350
+ st.markdown("# Mistral-7B-Instruct-v0.2")
351
+ st.markdown(result2)
352
+ #st.code(result2, language="python", line_numbers=True)
353
+
354
+
355
+
356
+
357
+
358
+
359
+ # πŸ” ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM - api_name: /update_with_rag_md
360
+ response2 = client.predict(
361
+ message=query, # str in 'parameter_13' Textbox component
362
+ llm_results_use=10,
363
+ database_choice="Semantic Search",
364
+ llm_model_picked="mistralai/Mistral-7B-Instruct-v0.2",
365
+ api_name="/update_with_rag_md"
366
+ )
367
+ st.markdown("# Mistral-7B-Instruct-v0.2 update_with_rag_md 0")
368
+ st.markdown(response2[0])
369
+ #st.code(response2[0], language="python", line_numbers=True, wrap_lines=True)
370
+
371
+ st.markdown("# Mistral-7B-Instruct-v0.2 update_with_rag_md 1")
372
+ st.markdown(response2[1])
373
+ #st.code(response2[1], language="python", line_numbers=True, wrap_lines=True)
374
+
375
+
376
+ # Persist AI Results to Markdown Files
377
+ try:
378
+ filename = generate_filename(result, "md")
379
+ create_file(filename, query, result)
380
+ #st.session_state.chat_history.append({"assistant": query, "ArXiV": result})
381
+ except:
382
+ st.markdown('1 error')
383
+ try:
384
+ filename = generate_filename(result2, "md")
385
+ create_file(filename, query, result2)
386
+ #st.session_state.chat_history.append({"assistant": query, "ArXiV": result2})
387
+ except:
388
+ st.markdown('2 error')
389
+ try:
390
+ filename = generate_filename(response2[0], "md")
391
+ create_file(filename, query, response2[0])
392
+ #st.session_state.chat_history.append({"assistant": query, "ArXiV": response2[0]})
393
+ except:
394
+ st.markdown('3 error')
395
+ try:
396
+ filename = generate_filename(response2[1], "md")
397
+ create_file(filename, query, response2[1])
398
+ #st.session_state.chat_history.append({"assistant": query, "ArXiV": response2[1]})
399
+ except:
400
+ st.markdown('4 error')
401
+
402
+
403
+ return result, result2, response2
404
+
405
+
406
+ # πŸ“ Generate a safe filename from the first few lines of content
407
+ def generate_filename_from_content(content, file_type="md"):
408
+ # Extract the first few lines or sentences
409
+ first_sentence = content.split('\n', 1)[0][:90] # Limit the length to 90 characters
410
+ # Remove special characters to make it a valid filename
411
+ safe_name = re.sub(r'[^\w\s-]', '', first_sentence)
412
+ # Limit length to be compatible with Windows and Linux
413
+ safe_name = safe_name[:50].strip() # Adjust length limit
414
+ return f"{safe_name}.{file_type}"
415
+
416
+
417
+ # πŸ’Ύ Create and save a file
418
+ def create_file_from_content(content, should_save=True):
419
+ if not should_save:
420
+ return
421
+ filename = generate_filename_from_content(content)
422
+ with open(filename, 'w', encoding='utf-8') as file:
423
+ file.write(content)
424
+ return filename
425
+
426
+
427
+ # πŸ“‚ Display list of saved .md files in the sidebar
428
+ def display_saved_files_in_sidebar():
429
+ all_files = glob.glob("*.md")
430
+ all_files.sort(reverse=True)
431
+ all_files = [file for file in all_files if not file.lower().startswith('readme')] # Exclude README.md
432
+ st.sidebar.markdown("## πŸ“ Saved Markdown Files")
433
+ for file in all_files:
434
+ col1, col2, col3 = st.sidebar.columns([6, 2, 1])
435
+ with col1:
436
+ st.markdown(f"πŸ“„ {file}")
437
+ with col2:
438
+ st.sidebar.download_button(
439
+ label="⬇️ Download",
440
+ data=open(file, 'rb').read(),
441
+ file_name=file
442
+ )
443
+ with col3:
444
+ if st.sidebar.button("πŸ—‘", key=f"delete_{file}"):
445
+ os.remove(file)
446
+ st.rerun()
447
+
448
+ def clone_record(container, clone_id):
449
+ try:
450
+ existing_doc = container.read_item(item=clone_id, partition_key=clone_id)
451
+ new_doc = existing_doc.copy()
452
+ new_doc['id'] = generate_unique_id() # Generate new unique ID with timestamp
453
+ new_doc['name'] = new_doc['id'] # Generate new unique ID with timestamp
454
+ new_doc['createdAt'] = datetime.utcnow().isoformat() # Update the creation time
455
+ new_doc['_rid'] = None # Reset _rid or any system-managed fields
456
+ new_doc['_self'] = None
457
+ new_doc['_etag'] = None
458
+ new_doc['_attachments'] = None
459
+ new_doc['_ts'] = None # Reset timestamp to be updated by Cosmos DB automatically
460
+ # Insert the cloned document
461
+ response = container.create_item(body=new_doc)
462
+ st.success(f"Cloned document saved successfully with ID: {new_doc['id']} πŸŽ‰")
463
+ # Refresh the documents in session state
464
+ st.session_state.documents = list(container.query_items(
465
+ query="SELECT * FROM c ORDER BY c._ts DESC",
466
+ enable_cross_partition_query=True
467
+ ))
468
+ except exceptions.CosmosResourceNotFoundError:
469
+ st.error(f"Document with ID {clone_id} not found for cloning.")
470
+ except exceptions.CosmosHttpResponseError as e:
471
+ st.error(f"HTTP error occurred: {str(e)} 🚨")
472
+ except Exception as e:
473
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
474
+
475
+
476
+ def create_new_blank_record(container):
477
+ try:
478
+ # Get the structure of the latest document (to preserve schema)
479
+ latest_doc = container.query_items(query="SELECT * FROM c ORDER BY c._ts DESC", enable_cross_partition_query=True, max_item_count=1)
480
+ if latest_doc:
481
+ new_doc_structure = latest_doc[0].copy()
482
+ else:
483
+ new_doc_structure = {}
484
+ new_doc = {key: "" for key in new_doc_structure.keys()} # Set all fields to blank
485
+ new_doc['id'] = generate_unique_id() # Generate new unique ID
486
+ new_doc['createdAt'] = datetime.utcnow().isoformat() # Set creation time
487
+ # Insert the new blank document
488
+ response = container.create_item(body=new_doc)
489
+ st.success(f"New blank document saved successfully with ID: {new_doc['id']} πŸŽ‰")
490
+ # Refresh the documents in session state
491
+ st.session_state.documents = list(container.query_items(
492
+ query="SELECT * FROM c ORDER BY c._ts DESC",
493
+ enable_cross_partition_query=True
494
+ ))
495
+ except exceptions.CosmosHttpResponseError as e:
496
+ st.error(f"HTTP error occurred: {str(e)} 🚨")
497
+ except Exception as e:
498
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
499
+
500
+
501
+ # Function to preprocess the pasted content
502
+ def preprocess_text(text):
503
+ # Replace CRLF and other newline variations with the JSON newline escape sequence
504
+ text = text.replace('\r\n', '\\n')
505
+ text = text.replace('\r', '\\n')
506
+ text = text.replace('\n', '\\n')
507
+ # Escape double quotes inside the text
508
+ text = text.replace('"', '\\"')
509
+ # Optionally remove or handle other special characters that might not be JSON-safe
510
+ # Here, we remove characters like tabs or non-ASCII characters (as an example)
511
+ text = re.sub(r'[\t]', ' ', text) # Replace tabs with spaces
512
+ text = re.sub(r'[^\x00-\x7F]+', '', text) # Remove non-ASCII characters
513
+ # Normalize spaces (strip leading/trailing whitespace)
514
+ text = text.strip()
515
+ return text
516
+
517
+
518
+
519
+ # 🎭 Main function - "All the world's a stage, and all the code merely players" -Shakespeare, probably
520
+ def main():
521
+ st.markdown("### πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent")
522
+
523
+ # 🎲 Session state vars - "Life is like a session state, you never know what you're gonna get"
524
+ if 'logged_in' not in st.session_state:
525
+ st.session_state.logged_in = False
526
+ if 'selected_records' not in st.session_state:
527
+ st.session_state.selected_records = []
528
+ if 'client' not in st.session_state:
529
+ st.session_state.client = None
530
+ if 'selected_database' not in st.session_state:
531
+ st.session_state.selected_database = None
532
+ if 'selected_container' not in st.session_state:
533
+ st.session_state.selected_container = None
534
+ if 'selected_document_id' not in st.session_state:
535
+ st.session_state.selected_document_id = None
536
+ if 'current_index' not in st.session_state:
537
+ st.session_state.current_index = 0
538
+ if 'cloned_doc' not in st.session_state:
539
+ st.session_state.cloned_doc = None
540
+
541
+ # πŸ” Query processing - "To search or not to search, that is the query"
542
+ try:
543
+ query_params = st.query_params
544
+ query = query_params.get('q') or query_params.get('query') or ''
545
+ if query:
546
+ result, result2, result3, response2 = search_glossary(query)
547
+
548
+ # πŸ’Ύ Save results - "Every file you save is a future you pave"
549
+ try:
550
+ if st.button("Save AI Output"):
551
+ filename = create_file_from_content(result)
552
+ st.success(f"File saved: {filename}")
553
+ filename = create_file_from_content(result2)
554
+ st.success(f"File saved: {filename}")
555
+ filename = create_file_from_content(result3)
556
+ st.success(f"File saved: {filename}")
557
+ filename = create_file_from_content(response2)
558
+ st.success(f"File saved: {filename}")
559
+
560
+ display_saved_files_in_sidebar()
561
+ except Exception as e:
562
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
563
+
564
+ # 🌟 Cosmos DB operations - "In Cosmos DB we trust, but we still handle errors we must"
565
+ try:
566
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result, result)
567
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result2, result2)
568
+ save_to_cosmos_db(st.session_state.cosmos_container, query, result3, result3)
569
+ save_to_cosmos_db(st.session_state.cosmos_container, query, response2[0], response2[0])
570
+ save_to_cosmos_db(st.session_state.cosmos_container, query, response2[1], response2[1])
571
+ except exceptions.CosmosHttpResponseError as e:
572
+ st.error(f"HTTP error occurred: {str(e)} 🚨")
573
+ except Exception as e:
574
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
575
+ st.stop()
576
+ except Exception as e:
577
+ st.markdown(' ')
578
+
579
+ # πŸ” Auth check - "With great keys come great connectivity"
580
+ if Key:
581
+ st.session_state.primary_key = Key
582
+ st.session_state.logged_in = True
583
+ else:
584
+ st.error("Cosmos DB Key is not set in environment variables. πŸ”‘βŒ")
585
+ return
586
+
587
+ if st.session_state.logged_in:
588
+ # 🌌 DB initialization - "In the beginning, there was connection string..."
589
+ try:
590
+ if st.session_state.client is None:
591
+ st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
592
+ # πŸ“š Navigation setup - "Navigation is not about where you are, but where you're going"
593
+ st.sidebar.title("πŸ™Git🌌CosmosπŸ’«πŸ—„οΈNavigator")
594
+ databases = get_databases(st.session_state.client)
595
+ selected_db = st.sidebar.selectbox("πŸ—ƒοΈ Select Database", databases)
596
+ st.markdown(CosmosDBUrl)
597
+
598
+ # πŸ”„ State management - "Change is the only constant in state management"
599
+ if selected_db != st.session_state.selected_database:
600
+ st.session_state.selected_database = selected_db
601
+ st.session_state.selected_container = None
602
+ st.session_state.selected_document_id = None
603
+ st.session_state.current_index = 0
604
+ st.rerun()
605
+
606
+ if st.session_state.selected_database:
607
+ database = st.session_state.client.get_database_client(st.session_state.selected_database)
608
+ containers = get_containers(database)
609
+ selected_container = st.sidebar.selectbox("πŸ“ Select Container", containers)
610
+
611
+ # πŸ”„ Container state handling - "Container changes, state arranges"
612
+ if selected_container != st.session_state.selected_container:
613
+ st.session_state.selected_container = selected_container
614
+ st.session_state.selected_document_id = None
615
+ st.session_state.current_index = 0
616
+ st.rerun()
617
+
618
+ if st.session_state.selected_container:
619
+ container = database.get_container_client(st.session_state.selected_container)
620
+ # πŸ“¦ Export functionality - "Pack it, zip it, ship it"
621
+ if st.sidebar.button("πŸ“¦ Export Container Data"):
622
+ download_link = archive_current_container(st.session_state.selected_database,
623
+ st.session_state.selected_container,
624
+ st.session_state.client)
625
+ if download_link.startswith('<a'):
626
+ st.markdown(download_link, unsafe_allow_html=True)
627
+ else:
628
+ st.error(download_link)
629
+
630
+ # πŸ“ Document handling - "Document, document, on the wall, who's the most recent of them all?"
631
+ documents = get_documents(container)
632
+ total_docs = len(documents)
633
+ # Add a slider to let the user choose how many documents to display
634
+ num_docs_to_display = st.slider(
635
+ "Select number of documents to display", 1, 20, 1
636
+ )
637
+ # Adjust the document display logic based on the slider value
638
+ if total_docs > num_docs_to_display:
639
+ documents_to_display = documents[:num_docs_to_display]
640
+ st.sidebar.info(f"Showing top {num_docs_to_display} most recent documents.")
641
+ else:
642
+ documents_to_display = documents
643
+ st.sidebar.info(f"Showing all {len(documents_to_display)} documents.")
644
+
645
+ if documents_to_display:
646
+ # 🎨 View options - "Different strokes for different folks"
647
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Run AI', 'Clone Document', 'New Record']
648
+ selected_view = st.sidebar.selectbox("Select Viewer/Editor", view_options, index=2)
649
+
650
+
651
+ if selected_view == 'Show as Markdown':
652
+ Label = '#### πŸ“„ Markdown view - Mark it down, mark it up'
653
+ st.markdown(Label)
654
+ total_docs = len(documents)
655
+ doc = documents[st.session_state.current_index]
656
+ # st.markdown(f"#### Document ID: {doc.get('id', '')}")
657
+
658
+ # πŸ•΅οΈ Value extraction - "Finding spaces in all the right places"
659
+ values_with_space = []
660
+ def extract_values(obj):
661
+ if isinstance(obj, dict):
662
+ for k, v in obj.items():
663
+ extract_values(v)
664
+ elif isinstance(obj, list):
665
+ for item in obj:
666
+ extract_values(item)
667
+ elif isinstance(obj, str):
668
+ if ' ' in obj:
669
+ values_with_space.append(obj)
670
+
671
+ extract_values(doc)
672
+ st.markdown("#### πŸ”— Links for Extracted Texts")
673
+ for term in values_with_space:
674
+ display_glossary_entity(term)
675
+
676
+ content = json.dumps(doc, indent=2)
677
+ st.markdown(f"```json\n{content}\n```")
678
+
679
+ # β¬…οΈβž‘οΈ Navigation - "Left and right, day and night"
680
+ col_prev, col_next = st.columns([1, 1])
681
+ with col_prev:
682
+ if st.button("⬅️ Previous", key='prev_markdown'):
683
+ if st.session_state.current_index > 0:
684
+ st.session_state.current_index -= 1
685
+ st.rerun()
686
+ with col_next:
687
+ if st.button("➑️ Next", key='next_markdown'):
688
+ if st.session_state.current_index < total_docs - 1:
689
+ st.session_state.current_index += 1
690
+ st.rerun()
691
+
692
+
693
+
694
+ elif selected_view == 'Show as Code Editor':
695
+ Label = '#### πŸ’» Code editor view'
696
+ st.markdown(Label)
697
+ total_docs = len(documents)
698
+ doc = documents[st.session_state.current_index]
699
+ # st.markdown(f"#### Document ID: {doc.get('id', '')}")
700
+ doc_str = st.text_area("Edit Document",
701
+ value=json.dumps(doc, indent=2),
702
+ height=300,
703
+ key=f'code_editor_{st.session_state.current_index}')
704
+
705
+ col_prev, col_next = st.columns([1, 1])
706
+ with col_prev:
707
+ if st.button("⬅️ Previous", key='prev_code'):
708
+ if st.session_state.current_index > 0:
709
+ st.session_state.current_index -= 1
710
+ st.rerun()
711
+ with col_next:
712
+ if st.button("➑️ Next", key='next_code'):
713
+ if st.session_state.current_index < total_docs - 1:
714
+ st.session_state.current_index += 1
715
+ st.rerun()
716
+
717
+ col_save, col_delete = st.columns([1, 1])
718
+ with col_save:
719
+ if st.button("πŸ’Ύ Save Changes", key=f'save_button_{st.session_state.current_index}'):
720
+ try:
721
+ updated_doc = json.loads(doc_str)
722
+ response = container.upsert_item(body=updated_doc)
723
+ if response:
724
+ st.success(f"Document {updated_doc['id']} saved successfully.")
725
+ st.session_state.selected_document_id = updated_doc['id']
726
+ st.rerun()
727
+ except Exception as e:
728
+ st.error(f"Error saving document: {str(e)}")
729
+
730
+ with col_delete:
731
+ if st.button("πŸ—‘οΈ Delete", key=f'delete_button_{st.session_state.current_index}'):
732
+ try:
733
+ current_doc = json.loads(doc_str)
734
+ # Direct deletion using container method with id and partition key
735
+ delete = container.delete_item(current_doc["id"], current_doc["id"])
736
+ if delete:
737
+ st.success(f"Document {current_doc['id']} deleted successfully.")
738
+ if st.session_state.current_index > 0:
739
+ st.session_state.current_index -= 1
740
+ st.rerun()
741
+ except Exception as e:
742
+ st.error(f"Error deleting document: {str(e)}")
743
+
744
+
745
+ elif selected_view == 'Show as Run AI':
746
+ Label = '#### ✏️ Run AI with wisdom, save with precision'
747
+ st.markdown(Label)
748
+ num_cols = len(documents_to_display)
749
+ cols = st.columns(num_cols)
750
+
751
+ for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
752
+ with col:
753
+
754
+ # st.markdown(f"##### Document ID: {doc.get('id', '')}")
755
+ editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
756
+ editable_doc = doc.copy()
757
+ editable_doc.pop('id', None)
758
+
759
+ # st.markdown(f"##### Document Name: {doc.get('name', '')}")
760
+ editable_id = st.text_input("Name", value=doc.get('name', ''), key=f'edit_name_{idx}')
761
+ editable_doc = doc.copy()
762
+ editable_doc.pop('name', None)
763
+
764
+ doc_str = st.text_area("Document Content (in JSON format)",
765
+ value=json.dumps(editable_doc, indent=2),
766
+ height=300,
767
+ key=f'doc_str_{idx}')
768
+
769
+ # πŸ’ΎπŸ€– Save and AI operations
770
+ col_ai, col_delete = st.columns(2)
771
+
772
+ with col_ai:
773
+ if st.button("πŸ€– Run AI", key=f'run_with_ai_button_{idx}'):
774
+
775
+
776
+
777
+
778
+ # Experiment to get content fields πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–
779
+ total_docs = len(documents)
780
+ doc = documents[st.session_state.current_index]
781
+ values_with_space = []
782
+ def extract_values2(obj):
783
+ if isinstance(obj, dict):
784
+ for k, v in obj.items():
785
+ extract_values2(v)
786
+ elif isinstance(obj, list):
787
+ for item in obj:
788
+ extract_values2(item)
789
+ elif isinstance(obj, str):
790
+ if ' ' in obj:
791
+ values_with_space.append(obj)
792
+ extract_values2(doc)
793
+ #st.markdown("#### πŸ”— Links for Extracted Texts")
794
+ for term in values_with_space:
795
+ display_glossary_entity(term)
796
+ search_glossary(term)
797
+
798
+ #content = json.dumps(doc, indent=2)
799
+ #st.markdown(f"```json\n{content}\n```")
800
+ # Experiment to get content fields πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–πŸ€–
801
+
802
+
803
+
804
+
805
+ #search_glossary(json.dumps(editable_doc, indent=2))
806
+
807
+
808
+ elif selected_view == 'Clone Document':
809
+ st.markdown("#### Clone a document:")
810
+
811
+ for idx, doc in enumerate(documents_to_display):
812
+ st.markdown(f"##### Original Document ID: {doc.get('id', '')}")
813
+
814
+ if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
815
+ # Create new document with unique ID and name
816
+ new_doc = {
817
+ 'id': str(uuid.uuid4()),
818
+ 'name': f"Clone_{str(uuid.uuid4())[:8]}",
819
+ **{k: v for k, v in doc.items() if k not in ['id', 'name', '_rid', '_self', '_etag', '_attachments', '_ts']}
820
+ }
821
+
822
+ # Show editable preview
823
+ edited_doc = st.text_area(
824
+ "Edit cloned document:",
825
+ value=json.dumps(new_doc, indent=2),
826
+ height=300,
827
+ key=f'edit_clone_{idx}'
828
+ )
829
+
830
+ if st.button("πŸ’Ύ Save Clone", key=f'save_clone_{idx}'):
831
+ try:
832
+ final_doc = json.loads(edited_doc)
833
+ # Use container.create_item() instead of update_record()
834
+ response = container.create_item(body=final_doc)
835
+ if response:
836
+ st.success(f"New cloned document created with ID: {final_doc['id']}")
837
+ st.rerun()
838
+ else:
839
+ st.error("Failed to create new document")
840
+ except Exception as e:
841
+ st.error(f"Error creating document: {str(e)}")
842
+
843
+
844
+ elif selected_view == 'New Record':
845
+ st.markdown("#### Create a new document:")
846
+
847
+ if st.button("πŸ€– Insert Auto-Generated Record"):
848
+ auto_doc = {
849
+ "id": generate_unique_id(),
850
+ "name": f"Auto-generated Record {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
851
+ "content": "This is an auto-generated record.",
852
+ "timestamp": datetime.now().isoformat()
853
+ }
854
+ success, message = save_or_clone_to_cosmos_db(container, document=auto_doc)
855
+ if success:
856
+ st.success(message)
857
+ st.rerun()
858
+ else:
859
+ st.error(message)
860
+ else:
861
+ new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
862
+ default_doc = {
863
+ "id": new_id,
864
+ "name": "New Document",
865
+ "content": "",
866
+ "timestamp": datetime.now().isoformat()
867
+ }
868
+ new_doc_str = st.text_area("Document Content (in JSON format)",
869
+ value=json.dumps(default_doc, indent=2),
870
+ height=300)
871
+
872
+ if st.button("βž• Create New Document"):
873
+ try:
874
+ # Preprocess the text before loading it into JSON
875
+ cleaned_doc_str = preprocess_text(new_doc_str)
876
+ new_doc = json.loads(cleaned_doc_str)
877
+ new_doc['id'] = new_id # Ensure ID matches input field
878
+
879
+ success, message = insert_record(container, new_doc)
880
+ if success:
881
+ st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
882
+ st.session_state.selected_document_id = new_doc['id']
883
+ st.rerun()
884
+ else:
885
+ st.error(message)
886
+ except json.JSONDecodeError as e:
887
+ st.error(f"Invalid JSON: {str(e)} 🚫")
888
+
889
+ st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
890
+ if st.session_state.selected_container:
891
+ if documents_to_display:
892
+ Label = '#### πŸ“Š Data display - Data tells tales that words cannot'
893
+ st.markdown(Label)
894
+ df = pd.DataFrame(documents_to_display)
895
+ st.dataframe(df)
896
+ else:
897
+ st.info("No documents to display. 🧐")
898
+
899
+
900
+ Label = '#### πŸ™ GitHub integration - Git happens'
901
+ st.subheader("πŸ™ GitHub Operations")
902
+ github_token = os.environ.get("GITHUB")
903
+ source_repo = st.text_input("Source GitHub Repository URL",
904
+ value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
905
+ new_repo_name = st.text_input("New Repository Name (for cloning)",
906
+ value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
907
+
908
+ col1, col2 = st.columns(2)
909
+ with col1:
910
+ if st.button("πŸ“₯ Clone Repository"):
911
+ if github_token and source_repo:
912
+
913
+ st.markdown(Label)
914
+ try:
915
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
916
+ download_github_repo(source_repo, local_path)
917
+ zip_filename = f"{new_repo_name}.zip"
918
+ create_zip_file(local_path, zip_filename[:-4])
919
+ st.markdown(get_download_link(zip_filename), unsafe_allow_html=True)
920
+ st.success("Repository cloned successfully! πŸŽ‰")
921
+ except Exception as e:
922
+ st.error(f"An error occurred: {str(e)} 😒")
923
+ finally:
924
+ if os.path.exists(local_path):
925
+ shutil.rmtree(local_path)
926
+ if os.path.exists(zip_filename):
927
+ os.remove(zip_filename)
928
+ else:
929
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
930
+
931
+ with col2:
932
+ if st.button("πŸ“€ Push to New Repository"):
933
+ if github_token and source_repo:
934
+
935
+ st.markdown(Label)
936
+ try:
937
+ g = Github(github_token)
938
+ new_repo = create_repo(g, new_repo_name)
939
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
940
+ download_github_repo(source_repo, local_path)
941
+ push_to_github(local_path, new_repo, github_token)
942
+ st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
943
+ except Exception as e:
944
+ st.error(f"An error occurred: {str(e)} 😒")
945
+ finally:
946
+ if os.path.exists(local_path):
947
+ shutil.rmtree(local_path)
948
+ else:
949
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
950
+
951
+
952
+ st.subheader("πŸ’¬ Chat with Claude")
953
+ user_input = st.text_area("Message πŸ“¨:", height=100)
954
+
955
+ if st.button("Send πŸ“¨"):
956
+ Label = '#### πŸ’¬ Chat functionality - Every chat is a chance to learn'
957
+ st.markdown(Label)
958
+ if user_input:
959
+ response = client.messages.create(
960
+ model="claude-3-sonnet-20240229",
961
+ max_tokens=1000,
962
+ messages=[
963
+ {"role": "user", "content": user_input}
964
+ ]
965
+ )
966
+ st.write("Claude's reply 🧠:")
967
+ st.write(response.content[0].text)
968
+ filename = generate_filename(user_input, "md")
969
+ create_file(filename, user_input, response.content[0].text)
970
+ st.session_state.chat_history.append({"user": user_input, "claude": response.content[0].text})
971
+ # Save to Cosmos DB
972
+ save_to_cosmos_db(container, user_input, response.content[0].text, "")
973
+
974
+
975
+
976
+ # πŸ“œ Chat history display - "History repeats itself, first as chat, then as wisdom"
977
+ st.subheader("Past Conversations πŸ“œ")
978
+ for chat in st.session_state.chat_history:
979
+ st.text_area("You said πŸ’¬:", chat["user"], height=100, disabled=True)
980
+ st.text_area("Claude replied πŸ€–:", chat["claude"], height=200, disabled=True)
981
+ st.markdown("---")
982
+
983
+
984
+ # πŸ“ File editor - "Edit with care, save with flair"
985
+ if hasattr(st.session_state, 'current_file'):
986
+ st.subheader(f"Editing: {st.session_state.current_file} πŸ› ")
987
+ new_content = st.text_area("File Content ✏️:", st.session_state.file_content, height=300)
988
+
989
+ # Preprocess the text before loading it into JSON - Added to protect copy paste into JSON to keep format.
990
+ cleaned_doc_str = preprocess_text(new_content)
991
+ new_doc = json.loads(cleaned_doc_str)
992
+ new_content = cleaned_doc_str
993
+
994
+ if st.button("Save Changes πŸ’Ύ"):
995
+ with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
996
+ file.write(new_content)
997
+ st.success("File updated successfully! πŸŽ‰")
998
+
999
+ # πŸ“‚ File management - "Manage many, maintain order"
1000
+ st.sidebar.title("πŸ“ File Management")
1001
+
1002
+ all_files = glob.glob("*.md")
1003
+ all_files.sort(reverse=True)
1004
+
1005
+ if st.sidebar.button("πŸ—‘ Delete All Files"):
1006
+ for file in all_files:
1007
+ os.remove(file)
1008
+ st.rerun()
1009
+
1010
+ if st.sidebar.button("⬇️ Download All Files"):
1011
+ zip_file = create_zip_of_files(all_files)
1012
+ st.sidebar.markdown(get_download_link(zip_file), unsafe_allow_html=True)
1013
+
1014
+ for file in all_files:
1015
+ col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
1016
+ with col1:
1017
+ if st.button("🌐", key="view_"+file):
1018
+ st.session_state.current_file = file
1019
+ st.session_state.file_content = load_file(file)
1020
+ with col2:
1021
+ st.markdown(get_download_link(file), unsafe_allow_html=True)
1022
+ with col3:
1023
+ if st.button("πŸ“‚", key="edit_"+file):
1024
+ st.session_state.current_file = file
1025
+ st.session_state.file_content = load_file(file)
1026
+ with col4:
1027
+ if st.button("πŸ—‘", key="delete_"+file):
1028
+ os.remove(file)
1029
+ st.rerun()
1030
+
1031
+ except exceptions.CosmosHttpResponseError as e:
1032
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
1033
+ except Exception as e:
1034
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
1035
+
1036
+ if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
1037
+ Label = '#### πŸšͺ Logout - All good things must come to an end'
1038
+ st.markdown(Label)
1039
+ st.session_state.logged_in = False
1040
+ st.session_state.selected_records.clear()
1041
+ st.session_state.client = None
1042
+ st.session_state.selected_database = None
1043
+ st.session_state.selected_container = None
1044
+ st.session_state.selected_document_id = None
1045
+ st.session_state.current_index = 0
1046
+ st.rerun()
1047
+
1048
+ if __name__ == "__main__":
1049
+ main()