acecalisto3 commited on
Commit
06e2a4b
·
verified ·
1 Parent(s): f74ca00

Update streamlit_app.py

Browse files
Files changed (1) hide show
  1. streamlit_app.py +223 -232
streamlit_app.py CHANGED
@@ -2,251 +2,242 @@ import streamlit as st
2
  import subprocess
3
  import os
4
  import logging
5
- import json
6
- import requests
7
- from streamlit.components.v1 import html
8
 
9
  # Configure logging
10
- logging.basicConfig(filename='supercoder_launcher.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 
 
 
 
11
 
12
- # Define repository and project directories
13
  REPO_DIR = os.path.join(os.getcwd(), "SuperCoder")
14
- PROJECT_DIR = os.getcwd()
15
 
16
- # Create requirements.txt
17
- def create_requirements_txt():
18
- requirements_content = "streamlit\n"
19
- try:
20
- with open(os.path.join(REPO_DIR, 'requirements.txt'), 'w') as f:
21
- f.write(requirements_content.strip())
22
- logging.info("requirements.txt created successfully.")
23
- except Exception as e:
24
- logging.error(f"Error creating requirements.txt: {str(e)}")
25
-
26
- # Create Dockerfile
27
- def create_dockerfile():
28
- dockerfile_content = """
29
- FROM python:3.9-slim
30
- WORKDIR /app
31
- # Install git
32
- RUN apt-get update && apt-get install -y git
33
- # Copy requirements first to leverage Docker cache
34
- COPY requirements.txt .
35
- RUN pip install -r requirements.txt
36
- # Copy the rest of the application
37
- COPY . .
38
- # Expose the Streamlit port
39
- EXPOSE 8501
40
- # Health check to ensure the container is running properly
41
- HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 CMD curl -f http://localhost:8501/_stcore/health || exit 1
42
- # Command to run the application
43
- ENTRYPOINT ["streamlit", "run", "app.py", "--server.address", "0.0.0.0"]
44
- """
45
- try:
46
- with open(os.path.join(REPO_DIR, 'Dockerfile'), 'w') as f:
47
- f.write(dockerfile_content.strip())
48
- logging.info("Dockerfile created successfully.")
49
- except Exception as e:
50
- logging.error(f"Error creating Dockerfile: {str(e)}")
51
-
52
- # Function to handle Hugging Face models, datasets, and spaces
53
- def handle_huggingface_request(link, instruction):
54
- # Example logic for handling Hugging Face models, datasets, and spaces
55
- if "huggingface.co" in link:
56
- # Process the link based on the type (model, dataset, space)
57
- if "models" in link:
58
- # Logic to deploy or modify a model
59
- logging.info(f"Processing Hugging Face model: {link}")
60
- # Add your model handling logic here
61
- elif "datasets" in link:
62
- # Logic to parse or combine datasets
63
- logging.info(f"Processing Hugging Face dataset: {link}")
64
- # Add your dataset handling logic here
65
- elif "spaces" in link:
66
- # Logic to modify and deploy a space
67
- logging.info(f"Processing Hugging Face space: {link}")
68
- # Add your space handling logic here
69
- elif "github.com" in link:
70
- # Logic to handle GitHub repositories
71
- logging.info(f"Processing GitHub repository: {link}")
72
- # Add your GitHub handling logic here
73
- else:
74
- logging.warning(f"Unsupported link: {link}")
75
-
76
- # Streamlit app interface
77
- def main():
78
- st.set_page_config(page_title="SuperCoder Launcher", page_icon="🚀")
79
- st.title("🚀 SuperCoder Launcher")
80
- st.markdown("""
81
- This application helps you set up and run SuperCoder.
82
- Follow the steps below to get started.
83
- """)
84
-
85
- # Initialize session state
86
- if 'setup_complete' not in st.session_state:
87
- st.session_state.setup_complete = False
88
- if 'install_complete' not in st.session_state:
89
- st.session_state.install_complete = False
90
- if 'terminal_output' not in st.session_state:
91
- st.session_state.terminal_output = []
92
 
93
- terminal_container = st.empty()
 
94
 
95
- def update_terminal(output):
96
- st.session_state.terminal_output.append(output)
97
- terminal_container.code('\n'.join(st.session_state.terminal_output))
 
 
 
 
 
98
 
99
- # Function to execute shell commands
100
- def execute_command(command: str, cwd: str = None) -> bool:
 
101
  try:
102
  process = subprocess.Popen(
103
- command,
104
- shell=True,
105
- cwd=cwd,
106
- stdout=subprocess.PIPE,
107
- stderr=subprocess.PIPE,
108
- text=True
109
  )
110
-
111
- while True:
112
- output = process.stdout.readline()
113
- if output == '' and process.poll() is not None:
114
- break
115
- if output:
116
- update_terminal(output.strip())
117
- logging.info(output.strip())
118
-
119
- stderr = process.stderr.read()
120
- if stderr:
121
- update_terminal(f"Error: {stderr.strip()}")
122
- logging.error(stderr.strip())
123
-
124
- return process.poll() == 0
125
  except Exception as e:
126
- update_terminal(f"Error executing command: {str(e)}")
127
- logging.error(f"Error executing command: {str(e)}")
128
- return False
129
-
130
- # Input fields for Hugging Face models, datasets, spaces, and GitHub links
131
- st.subheader("Input Links")
132
- huggingface_link = st.text_input("Hugging Face Model/Dataset/Space Link")
133
- github_link = st.text_input("GitHub Repository Link")
134
- instruction = st.text_area("Instructions for Processing")
135
-
136
- if st.button("Submit"):
137
- if huggingface_link or github_link:
138
- if huggingface_link:
139
- handle_huggingface_request(huggingface_link, instruction)
140
- if github_link:
141
- handle_huggingface_request(github_link, instruction)
142
- st.success("Request processed. Check terminal for details.")
143
- else:
144
- st.error("Please provide at least one link.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
- # Setup steps
147
- with st.expander("1. Clone Repository", expanded=not st.session_state.setup_complete):
148
- if st.button("Clone SuperCoder"):
 
 
 
 
 
 
149
  with st.spinner("Cloning repository..."):
150
- if os.path.exists(REPO_DIR):
151
- update_terminal("Repository already exists. Skipping clone.")
152
- logging.info("Repository already exists. Skipping clone.")
 
 
 
153
  else:
154
- success = execute_command(
155
- "git clone https://github.com/TransformerOptimus/SuperCoder",
156
- PROJECT_DIR
157
- )
158
- if success:
159
- create_requirements_txt()
160
- create_dockerfile()
161
- st.session_state.setup_complete = True
162
- st.success("Repository cloned successfully.")
163
- else:
164
- st.error("Failed to clone the repository. Check logs for details.")
165
-
166
- with st.expander("2. Build and Run Docker Container", expanded=st.session_state.setup_complete and not st.session_state.install_complete):
167
- if st.button("Build and Run Container", disabled=not st.session_state.setup_complete):
168
- with st.spinner("Building and running Docker container..."):
169
- # Build Docker image
170
- build_success = execute_command(
171
- "docker build -t supercoder .",
172
- REPO_DIR
173
- )
174
-
175
- if build_success:
176
- # Run Docker container
177
- run_success = execute_command(
178
- "docker run -d -p 8501:8501 --name supercoder_container supercoder",
179
- REPO_DIR
180
- )
181
-
182
- if run_success:
183
- st.session_state.install_complete = True
184
- st.success("Docker container is running!")
185
- else:
186
- st.error("Failed to run the Docker container. Check logs for details.")
187
- else:
188
- st.error("Failed to build the Docker image. Check logs for details.")
189
-
190
- with st.expander("3. Access Application", expanded=st.session_state.install_complete):
191
- if st.session_state.install_complete:
192
- st.markdown("""
193
- The application is running! Access it at:
194
-
195
- [http://localhost:8501](http://localhost:8501)
196
- """)
197
-
198
- if st.button("Stop Container"):
199
- execute_command("docker stop supercoder_container")
200
- execute_command("docker rm supercoder_container")
201
- st.session_state.install_complete = False
202
- st.success("Docker container stopped and removed.")
203
-
204
- # Display terminal output
205
- st.markdown("### Terminal Output")
206
- terminal_container.code('\n'.join(st.session_state.terminal_output))
207
-
208
- # Add a clear terminal button
209
- if st.button("Clear Terminal"):
210
- st.session_state.terminal_output = []
211
- st.success("Terminal cleared.")
212
-
213
- # Add a reset button
214
- if st.button("Reset Setup"):
215
- if st.session_state.install_complete:
216
- execute_command("docker stop supercoder_container")
217
- execute_command("docker rm supercoder_container")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  st.session_state.setup_complete = False
219
- st.session_state.install_complete = False
220
- st.session_state.terminal_output = []
221
- st.success("Setup reset.")
222
-
223
- # Embed an interactive terminal
224
- terminal_html = """
225
- <div id="terminal" style="width: 100%; height: 400px; border: 1px solid black;"></div>
226
- <script>
227
- var term = new Terminal();
228
- var fitAddon = new Fit Addon.FitAddon();
229
- term.loadAddon(fitAddon);
230
- term.open(document.getElementById('terminal'));
231
- fitAddon.fit();
232
- term.onData(function(data) {
233
- // Send data to Python backend
234
- var xhr = new XMLHttpRequest();
235
- xhr.open("POST", "/send_data", true);
236
- xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
237
- xhr.send(JSON.stringify({data: data}));
238
- });
239
- // Receive data from Python backend
240
- window.addEventListener('message', function(event) {
241
- var message = event.data;
242
- if (message.type === 'terminal_output') {
243
- term.write(message.output);
244
- }
245
- });
246
- </script>
247
- """
248
-
249
- html(terminal_html, height=400)
250
-
251
- if __name__ == "__main__":
252
- main()
 
2
  import subprocess
3
  import os
4
  import logging
5
+ import threading
6
+ import time
7
+ from huggingface_hub import snapshot_download
8
 
9
  # Configure logging
10
+ logging.basicConfig(
11
+ filename='supercoder_launcher.log',
12
+ level=logging.INFO,
13
+ format='%(asctime)s - %(levelname)s - %(message)s'
14
+ )
15
 
16
+ # Directories
17
  REPO_DIR = os.path.join(os.getcwd(), "SuperCoder")
 
18
 
19
+ # Session state initialization
20
+ if 'terminal_output' not in st.session_state:
21
+ st.session_state.terminal_output = []
22
+ if 'setup_complete' not in st.session_state:
23
+ st.session_state.setup_complete = False
24
+ if 'running' not in st.session_state:
25
+ st.session_state.running = False
26
+
27
+ # ---------- Utility functions ----------
28
+ def log_terminal(line: str):
29
+ st.session_state.terminal_output.append(line)
30
+ logging.info(line)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ def clear_terminal():
33
+ st.session_state.terminal_output = []
34
 
35
+ def get_command_output(command: str, cwd: str = None) -> str:
36
+ try:
37
+ result = subprocess.run(
38
+ command, shell=True, cwd=cwd, capture_output=True, text=True, timeout=60
39
+ )
40
+ return result.stdout + "\n" + result.stderr
41
+ except Exception as e:
42
+ return f"Error executing command: {str(e)}"
43
 
44
+ def run_command_background(command: str, cwd: str = None):
45
+ log_terminal(f"> {command}")
46
+ def target():
47
  try:
48
  process = subprocess.Popen(
49
+ command, shell=True, cwd=cwd,
50
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
51
+ text=True, bufsize=1, universal_newlines=True
 
 
 
52
  )
53
+ for line in process:
54
+ if line:
55
+ log_terminal(line.rstrip())
56
+ returncode = process.wait()
57
+ log_terminal(f"Process finished with return code: {returncode}")
 
 
 
 
 
 
 
 
 
 
58
  except Exception as e:
59
+ log_terminal(f"Exception in background command: {str(e)}")
60
+ threading.Thread(target=target, daemon=True).start()
61
+ st.success("Command started in background. Refresh terminal to see progress.")
62
+
63
+ # Hugging Face handling (enhanced)
64
+ def handle_huggingface(link: str, instruction: str, hf_token: str = None):
65
+ log_terminal(f"Processing Hugging Face link: {link}")
66
+ log_terminal(f"Instruction: {instruction}")
67
+ if "spaces" in link:
68
+ parts = link.split("huggingface.co/spaces/")[-1].strip("/")
69
+ clone_url = f"https://huggingface.co/spaces/{parts}"
70
+ if hf_token:
71
+ clone_url = f"https:{hf_token}@huggingface.co/spaces/{parts}"
72
+ dir_name = parts.split("/")[-1]
73
+ cmd = f"git clone {clone_url} workspaces/{dir_name}"
74
+ run_command_background(cmd, cwd=REPO_DIR)
75
+ elif "datasets" in link or "models" in link:
76
+ repo_id = link.split("huggingface.co/")[-1].strip("/")
77
+ local_dir = os.path.join(REPO_DIR, "models", repo_id.split("/")[-1])
78
+ try:
79
+ path = snapshot_download(
80
+ repo_id=repo_id,
81
+ local_dir=local_dir,
82
+ token=hf_token or None,
83
+ ignore_patterns=["*.bin"] if "small" in instruction.lower() else None
84
+ )
85
+ log_terminal(f"Downloaded {repo_id} → {path}")
86
+ except Exception as e:
87
+ log_terminal(f"HF download error: {str(e)}")
88
+ else:
89
+ log_terminal("Unsupported Hugging Face link type.")
90
+
91
+ # ---------- Main UI ----------
92
+ st.set_page_config(page_title="SuperCoder Advanced Launcher", page_icon="🚀", layout="wide")
93
+ st.title("🚀 SuperCoder Advanced Launcher")
94
+ st.markdown("Full-featured launcher for [TransformerOptimus/SuperCoder](https://github.com/TransformerOptimus/SuperCoder) with Docker Compose, .env config, live logs, preview, and Hugging Face/GitHub integrations.")
95
 
96
+ tabs = st.tabs(["Setup", "Config", "Run", "Logs & Status", "Preview", "Integrations", "Terminal"])
97
+
98
+ with tabs[0]: # Setup
99
+ st.subheader("Repository Management")
100
+ repo_git = os.path.join(REPO_DIR, ".git")
101
+ cloned = os.path.isdir(repo_git)
102
+
103
+ if not cloned:
104
+ if st.button("Clone SuperCoder Repository", type="primary"):
105
  with st.spinner("Cloning repository..."):
106
+ cmd = f"git clone https://github.com/TransformerOptimus/SuperCoder {REPO_DIR}"
107
+ success = subprocess.run(cmd, shell=True, capture_output=True, text=True).returncode == 0
108
+ if success:
109
+ st.session_state.setup_complete = True
110
+ st.success("Repository cloned successfully.")
111
+ st.rerun()
112
  else:
113
+ st.error("Clone failed. Check logs.")
114
+ else:
115
+ st.success("✅ Repository cloned")
116
+ st.session_state.setup_complete = True
117
+ if st.button("Update Repository (git pull)"):
118
+ with st.spinner("Pulling latest changes..."):
119
+ run_command_background("git pull", cwd=REPO_DIR)
120
+
121
+ with tabs[1]: # Config
122
+ st.subheader(".env Configuration (API keys, etc.)")
123
+ env_path = os.path.join(REPO_DIR, ".env")
124
+ default_env = """OPENAI_API_KEY=sk-...
125
+ ANTHROPIC_API_KEY=...
126
+ HF_TOKEN=hf_...
127
+ # Add other keys as needed
128
+ """
129
+ if os.path.exists(env_path):
130
+ with open(env_path) as f:
131
+ env_content = f.read()
132
+ else:
133
+ env_content = default_env
134
+
135
+ new_env = st.text_area(".env content", value=env_content, height=400)
136
+ if st.button("Save .env"):
137
+ try:
138
+ with open(env_path, "w") as f:
139
+ f.write(new_env)
140
+ st.success(".env saved successfully.")
141
+ except Exception as e:
142
+ st.error(f"Save failed: {e}")
143
+
144
+ with tabs[2]: # Run
145
+ st.subheader("Docker Compose Controls")
146
+ col1, col2, col3 = st.columns(3)
147
+ with col1:
148
+ if st.button("Start / Rebuild", type="primary", disabled=not st.session_state.setup_complete):
149
+ run_command_background("docker compose up --build -d", cwd=REPO_DIR)
150
+ st.session_state.running = True
151
+ with col2:
152
+ if st.button("Stop"):
153
+ run_command_background("docker compose down", cwd=REPO_DIR)
154
+ st.session_state.running = False
155
+ with col3:
156
+ if st.button("Restart"):
157
+ run_command_background("docker compose restart", cwd=REPO_DIR)
158
+
159
+ if st.button("Full Rebuild (down + up --build)"):
160
+ run_command_background("docker compose down && docker compose up --build -d", cwd=REPO_DIR)
161
+
162
+ with tabs[3]: # Logs & Status
163
+ st.subheader("Service Status & Logs")
164
+ auto = st.checkbox("Auto-refresh every 8 seconds")
165
+ if auto:
166
+ st.autorefresh(interval=8000, key="logsrefresh")
167
+
168
+ c1, c2 = st.columns(2)
169
+ with c1:
170
+ st.markdown("**docker compose ps**")
171
+ status = get_command_output("docker compose ps", cwd=REPO_DIR)
172
+ st.code(status)
173
+ with c2:
174
+ st.markdown("**Recent logs**")
175
+ logs = get_command_output("docker compose logs --tail=1000", cwd=REPO_DIR)
176
+ st.code(logs, language="log")
177
+
178
+ with tabs[4]: # Preview
179
+ st.subheader("Live Application Preview")
180
+ if st.session_state.running or "Up" in get_command_output("docker compose ps -q", cwd=REPO_DIR):
181
+ st.components.v1.iframe("http://localhost:3000", height=900, scrolling=True)
182
+ else:
183
+ st.warning("Application not running. Start it in the Run tab first.")
184
+
185
+ with tabs[5]: # Integrations
186
+ st.subheader("Hugging Face & GitHub Integrations")
187
+ hf_token = st.text_input("Hugging Face Token (for private repos)", type="password")
188
+ link = st.text_input("Hugging Face or GitHub Link")
189
+ instruction = st.text_area("Instructions (e.g., 'small model only', path hints)")
190
+ if st.button("Process Link"):
191
+ if not link:
192
+ st.error("Provide a link.")
193
+ else:
194
+ if "huggingface.co" in link:
195
+ handle_huggingface(link, instruction, hf_token)
196
+ elif "github.com" in link:
197
+ dir_name = link.split("/")[-1].replace(".git", "")
198
+ cmd = f"git clone {link} workspaces/{dir_name}"
199
+ run_command_background(cmd, cwd=REPO_DIR)
200
+ st.success("Processing started.")
201
+
202
+ st.markdown("---")
203
+ st.subheader("Manual HF Model/Dataset Download")
204
+ repo_id = st.text_input("Repo ID (e.g. meta-llama/Llama-3-8B)")
205
+ target_dir = st.text_input("Target subdirectory (relative to SuperCoder)", default="models/custom")
206
+ if st.button("Download Now"):
207
+ full_path = os.path.join(REPO_DIR, target_dir)
208
+ os.makedirs(full_path, exist_ok=True)
209
+ try:
210
+ snapshot_download(repo_id=repo_id, local_dir=full_path, token=hf_token or None)
211
+ st.success(f"Downloaded to {full_path}")
212
+ except Exception as e:
213
+ st.error(str(e))
214
+
215
+ with tabs[6]: # Terminal
216
+ st.subheader("Command Output Terminal")
217
+ st.code("\n".join(st.session_state.terminal_output), language="bash")
218
+ col1, col2 = st.columns(2)
219
+ with col1:
220
+ if st.button("Refresh Terminal"):
221
+ st.rerun()
222
+ with col2:
223
+ if st.button("Clear Terminal"):
224
+ clear_terminal()
225
+ st.rerun()
226
+
227
+ st.sidebar.markdown("### Quick Actions")
228
+ if st.sidebar.button("Full Reset (stop + remove repo)"):
229
+ if st.sidebar.checkbox("Confirm dangerous action"):
230
+ run_command_background("docker compose down -v", cwd=REPO_DIR)
231
+ if os.path.exists(REPO_DIR):
232
+ import shutil
233
+ shutil.rmtree(REPO_DIR)
234
  st.session_state.setup_complete = False
235
+ st.session_state.running = False
236
+ clear_terminal()
237
+ st.success("Reset complete.")
238
+
239
+ st.sidebar.markdown("---")
240
+ st.sidebar.caption(f"Launcher running from: {os.getcwd()}")
241
+ st.sidebar.caption("SuperCoder directory: ./SuperCoder")
242
+
243
+ Status: CONVERGED