provisorisches run

This commit is contained in:
leart-ramushi 2026-05-26 16:17:50 +02:00
parent d9a46ba701
commit da1d22ec56
4 changed files with 121 additions and 64 deletions

View File

@ -1,12 +1,41 @@
class ExecutionEngine:
"""
Platzhalter für die Code-Ausführung [1]
"""
def __init__(self):
pass
import subprocess
import sys
from pathlib import Path
def execute_code(self):
"""
Führt Code nicht aus, sondern gibt einen Status aus [1]
"""
return "Code wurde nicht ausgeführt (Platzhalter)"
class ExecutionEngine:
def run_file(self, filepath: str) -> dict:
path = Path(filepath)
if not path.exists():
return {"stdout": "", "stderr": f"File not found: {filepath}", "returncode": -1}
ext = path.suffix.lower()
if ext == ".py":
cmd = [sys.executable, str(path)]
elif ext == ".js":
cmd = ["node", str(path)]
elif ext == ".sh":
cmd = ["bash", str(path)]
else:
return {"stdout": "", "stderr": f"Unsupported file type: {ext}", "returncode": -1}
try:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=30,
cwd=str(path.parent),
)
return {
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode,
}
except subprocess.TimeoutExpired:
return {"stdout": "", "stderr": "Timed out after 30 seconds.", "returncode": -1}
except FileNotFoundError as e:
return {"stdout": "", "stderr": f"Runtime not found: {e}", "returncode": -1}
except Exception as e:
return {"stdout": "", "stderr": f"Error: {e}", "returncode": -1}

View File

@ -1,5 +1,6 @@
from pathlib import Path
class FileManager:
"""
Handles file reading and writing

View File

@ -1,89 +1,109 @@
import sys
import os
import tkinter as tk
from tkinter import filedialog
from pathlib import Path
import streamlit as st
from streamlit_tree_select import tree_select
# ---------------- PATH FIX ----------------
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# ---------------- BACKEND ----------------
from backend.file_manager import FileManager
from ui.navigation import FileNavigation
from ui.chat import ChatInterface
from ui.editor import CodeEditor
from ui.output import OutputDisplay
from backend.chat_manager import ChatManager
from backend.execution_engine import ExecutionEngine
# ---------------- PAGE ----------------
# ---------------- PAGE CONFIG ----------------
st.set_page_config(
page_title="AI Code Editor",
page_icon="💻",
layout="wide"
layout="wide",
)
# ---------------- FOLDER PICKER ----------------
def pick_folder():
root = tk.Tk()
root.withdraw()
root.wm_attributes("-topmost", 1)
folder = filedialog.askdirectory(title="Select project folder")
root.destroy()
return folder if folder else None
# ---------------- SIDEBAR ----------------
def render_sidebar():
st.sidebar.title("File Explorer")
st.sidebar.title("📁 File Explorer")
navigation = FileNavigation()
tree_data = navigation.build_tree(Path.cwd())
root_folder = st.session_state.get("root_folder")
with st.sidebar:
# --- Button on top ---
if st.button("📂 Choose Folder", key="pick_folder"):
picked = pick_folder()
if picked:
st.session_state.root_folder = picked
st.rerun()
if root_folder:
st.caption(f" {Path(root_folder).name}")
st.markdown("---")
# --- Tree below ---
if root_folder:
try:
root_path = Path(root_folder)
if root_path.exists() and root_path.is_dir():
navigation = FileNavigation()
tree_data = navigation.build_tree(root_path)
selection = tree_select(
tree_data,
check_model="leaf",
only_leaf_checkboxes=True
)
if selection and selection.get("checked"):
return selection["checked"][0]
else:
st.warning("Folder not found.")
except Exception:
st.error("Could not load folder.")
else:
st.info("No folder selected yet.")
return None
# ---------------- MAIN ----------------
def main():
file_manager = FileManager()
chat_manager = ChatManager()
execution_engine = ExecutionEngine()
# ---------------- STATE ----------------
if "root_folder" not in st.session_state:
st.session_state.root_folder = None
if "selected_file" not in st.session_state:
st.session_state.selected_file = None
if "active_file" not in st.session_state:
st.session_state.active_file = None
if "editor_content" not in st.session_state:
st.session_state.editor_content = ""
if "last_applied_content" not in st.session_state:
st.session_state.last_applied_content = ""
if "run_result" not in st.session_state:
st.session_state.run_result = None
# ---------------- FILE SELECT ----------------
selected_file = render_sidebar()
if selected_file:
st.session_state.selected_file = selected_file
current_file = st.session_state.selected_file
# ---------------- FILE SWITCH ----------------
if current_file != st.session_state.active_file:
st.session_state.active_file = current_file
st.session_state.run_result = None # clear output on file switch
if current_file:
content = file_manager.read_file(current_file)
st.session_state.editor_content = content
@ -91,55 +111,63 @@ def main():
else:
st.session_state.editor_content = ""
st.sidebar.markdown("---")
st.sidebar.caption("AI Code Editor")
# ---------------- MAIN UI ----------------
if st.session_state.active_file:
col1, col2 = st.columns([3, 2])
with col1:
st.subheader(f"Editing: {Path(st.session_state.active_file).name}")
# --- File name + Run button on same row ---
title_col, btn_col = st.columns([5, 1])
with title_col:
st.subheader(f"✏️ {Path(st.session_state.active_file).name}")
with btn_col:
run_clicked = st.button("▶ Run", type="primary", use_container_width=True)
editor = CodeEditor()
# IMPORTANT: only updates AFTER APPLY
new_value = editor.display_code(
st.session_state.editor_content,
filename=st.session_state.active_file
)
# ---------------- APPLY DETECTION ----------------
# Apply only triggers when Streamlit reruns with new value
if new_value is not None:
if new_value != st.session_state.last_applied_content:
st.session_state.editor_content = new_value
st.session_state.last_applied_content = new_value
file_manager.save_file(st.session_state.active_file, new_value)
st.success("Saved ✔")
file_manager.save_file(
st.session_state.active_file,
new_value
# --- Run execution ---
if run_clicked:
with st.spinner("Running…"):
st.session_state.run_result = execution_engine.run_file(
st.session_state.active_file
)
st.success("Saved via Apply ✔")
with col2:
chat = ChatInterface()
chat.display_chat(chat_manager)
output = OutputDisplay()
output.display_execution(execution_engine)
# --- Output panel ---
result = st.session_state.run_result
if result is not None:
st.markdown("---")
success = result["returncode"] == 0
status = "✅ Exited 0" if success else f"❌ Exited {result['returncode']}"
st.caption(f"Output — {status}")
if result["stdout"]:
st.code(result["stdout"], language="text")
if result["stderr"]:
st.code(result["stderr"], language="text")
if not result["stdout"] and not result["stderr"]:
st.caption("No output.")
else:
st.info("Select a file from the explorer 👈")
st.info("Select a file from the explorer")
if __name__ == "__main__":
main()

View File

@ -28,7 +28,6 @@ class CodeEditor:
language=language,
theme="chrome",
key=f"ace_{filename}",
height=500,
font_size=14,
tab_size=4,
wrap=False,