diff --git a/src/main.py b/src/main.py
index b8d2484..77b2398 100644
--- a/src/main.py
+++ b/src/main.py
@@ -20,91 +20,22 @@ st.set_page_config(
layout="wide"
)
-st.markdown(""" """, unsafe_allow_html=True)
-
-# ---------------- CHAT PANEL INJECTION ----------------
-def inject_chat_panel(is_open: bool):
- st.iframe(f"""
-
- """, height=1)
+st.markdown("""
+
+""", unsafe_allow_html=True)
# ---------------- MAIN ----------------
def main():
file_manager = FileManager()
navigation = FileNavigation()
+ chat = ChatInterface()
chat_manager = ChatManager()
execution_engine = ExecutionEngine()
output_display = OutputDisplay()
@@ -146,21 +77,19 @@ def main():
else:
st.session_state.editor_content = ""
- inject_chat_panel(st.session_state.chat_open)
+ chat.inject_panel(st.session_state.chat_open)
# ---------------- MAIN UI ----------------
if st.session_state.active_file:
- 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)
+ st.subheader(f"✏️ {Path(st.session_state.active_file).name}")
editor = CodeEditor()
- new_value = editor.display_code(
+ new_value, run_clicked = editor.display_code(
st.session_state.editor_content,
filename=st.session_state.active_file
)
+
+ # ---------------- APPLY DETECTION ----------------
if new_value is not None:
if new_value != st.session_state.last_applied_content:
st.session_state.editor_content = new_value
@@ -168,6 +97,7 @@ def main():
file_manager.save_file(st.session_state.active_file, new_value)
st.success("Saved ✔")
+ # ---------------- RUN ----------------
if run_clicked:
with st.spinner("Running…"):
st.session_state.run_result = execution_engine.run_file(
diff --git a/src/ui/chat.py b/src/ui/chat.py
index a5711fd..c88dcc8 100644
--- a/src/ui/chat.py
+++ b/src/ui/chat.py
@@ -1,45 +1,116 @@
import streamlit as st
+
class ChatInterface:
"""
- Chat Interface für KI-Interaktion [1]
+ Chat Interface for AI interaction, including the right-side slide-out panel.
"""
-
+
def __init__(self):
self.chat_messages = []
-
+
+ # ---------------- PANEL INJECTION ----------------
+ def inject_panel(self, is_open: bool):
+ """Injects or removes the fixed right-side AI chat panel via st.iframe."""
+ st.iframe(f"""
+
+ """, height=1)
+
+ # ---------------- CHAT DISPLAY ----------------
def display_chat(self, chat_manager):
- """
- Zeigt die Chat-Schnittstelle mit Konversationsverlauf [1]
- """
- st.title("🤖 KI-Assistent")
-
- # Chat History anzeigen
+ """Renders the Streamlit chat interface (used when not in panel mode)."""
+ st.title("AI Assistant")
+
for message in self.chat_messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
-
- # User Input
- if prompt := st.chat_input("Frage zum Code stellen..."):
- # User Nachricht anzeigen
+
+ if prompt := st.chat_input("Ask about your code..."):
self.chat_messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
-
- # AI Antwort generieren (via ChatManager)
+
with st.chat_message("assistant"):
response = chat_manager.generate_response(prompt)
st.markdown(response)
self.chat_messages.append({"role": "assistant", "content": response})
-
- def add_message(self, role, content):
- """
- Fügt eine Nachricht zur Konversation hinzu
- """
+
+ # ---------------- HELPERS ----------------
+ def add_message(self, role: str, content: str):
self.chat_messages.append({"role": role, "content": content})
-
+
def clear_history(self):
- """
- Löscht den Chat-Verlauf
- """
self.chat_messages.clear()
\ No newline at end of file
diff --git a/src/ui/editor.py b/src/ui/editor.py
index 6798a03..ec7d1b8 100644
--- a/src/ui/editor.py
+++ b/src/ui/editor.py
@@ -1,29 +1,44 @@
from streamlit_ace import st_ace
+import streamlit as st
+
class CodeEditor:
- def detect_language(self, filename):
-
+ def detect_language(self, filename: str) -> str:
mapping = {
- ".py": "python",
- ".js": "javascript",
+ ".py": "python",
+ ".js": "javascript",
".html": "html",
- ".css": "css",
+ ".css": "css",
".json": "json",
- ".md": "markdown",
+ ".md": "markdown",
}
-
for ext, lang in mapping.items():
if filename.endswith(ext):
return lang
-
return "text"
- def display_code(self, code_content, filename=""):
-
+ def display_code(self, code_content: str, filename: str = "") -> tuple:
+ """
+ Renders a toolbar row (Apply is built into st_ace, Run is next to it)
+ then the ACE editor below.
+ Returns (new_value, run_clicked) where new_value is None until Apply is hit.
+ """
language = self.detect_language(filename)
- return st_ace(
+ # --- Toolbar: filename label + Run button aligned right ---
+ label_col, run_col = st.columns([6, 1])
+ with label_col:
+ st.caption(f" {filename.split('/')[-1] or filename}" if filename else "")
+ with run_col:
+ run_clicked = st.button(
+ "▶ Run",
+ key=f"run_{filename}",
+ type="primary",
+ use_container_width=True
+ )
+
+ new_value = st_ace(
value=code_content,
language=language,
theme="chrome",
@@ -31,7 +46,9 @@ class CodeEditor:
font_size=14,
tab_size=4,
wrap=False,
- auto_update=False,
+ auto_update=False,
show_gutter=True,
- show_print_margin=False
- )
\ No newline at end of file
+ show_print_margin=False,
+ )
+
+ return new_value, run_clicked
\ No newline at end of file