improvments

This commit is contained in:
Livio Meuli 2026-05-25 19:02:20 +02:00
parent 3891007fb2
commit efdd9351b3
5 changed files with 54 additions and 11 deletions

View File

@ -39,7 +39,7 @@ def main():
"""
<style>
.block-container { padding-top: 1rem; }
[data-testid="stSidebarContent"] { padding-top: 0rem; margin-top: -2rem; }
[data-testid="stSidebarContent"] { padding-top: 1rem; }
</style>
""",
unsafe_allow_html=True,

View File

@ -1,18 +1,17 @@
"""Chat view — renders both the normal chat interface and the Coding Agent mode."""
import asyncio
import json
from pathlib import Path
import streamlit as st
from backend.managers.chat_manager import ChatManager
from backend.managers.system_prompter import SystemPrompter
from backend.managers.search_manager import SearchManager
from backend.agent.coding_agent import CodingAgent
from backend.managers.debug_logger import get_logger
logger = get_logger(__name__)
import asyncio
import json
logger = get_logger(__name__)
# ── Agent Mode helpers ────────────────────────────────────────────────────────
@ -377,6 +376,32 @@ def render_normal_chat():
user sends a message, they are prepended to that message as a context block.
"""
logger.info("Chat mode")
chat_manager: ChatManager = st.session_state.chat_manager
# Apply model/token overrides from the Settings panel before any API call.
if st.session_state.get("selected_model"):
chat_manager.model = st.session_state.selected_model
if "chat_max_tokens" in st.session_state:
chat_manager.max_tokens = st.session_state.chat_max_tokens
# Consume a debug message forwarded from the editor's "Debug with AI" button.
pending_debug = st.session_state.pop("pending_debug_message", None)
if pending_debug:
if not chat_manager.get_history():
system_prompt = SystemPrompter.generate_prompt(_build_file_context())
chat_manager.add_message("system", system_prompt)
with st.spinner("Sending debug info to AI..."):
try:
ai_response = chat_manager.send_message(pending_debug)
except Exception as e:
ai_response = f"Error: {e}"
st.session_state.chat_history.append({"role": "user", "content": pending_debug})
st.session_state.chat_history.append(
{"role": "assistant", "content": ai_response}
)
st.rerun()
return
# Replay the conversation history as chat bubbles (skip system messages).
for message in st.session_state.chat_history:
if message["role"] == "system":
@ -430,7 +455,6 @@ def render_normal_chat():
return
# ── Normal chat message ───────────────────────────────────────────────
chat_manager = st.session_state.chat_manager
search_results = st.session_state.get("search_results", [])
# 5g — System-prompt logic: inject on first message, update on file change.
@ -473,8 +497,8 @@ def render_normal_chat():
if st.button("🗑️ Clear Chat"):
_clear_chat_dialog()
# REVIEW: duplicate widget key — "agent_mode" toggle is already rendered inside render_agent_mode();
# having two st.toggle calls with the same key on the same page will raise a DuplicateWidgetID error.
# Toggle to switch to Agent Mode (render_normal_chat and render_agent_mode are
# mutually exclusive, so the same key here causes no DuplicateWidgetID conflict).
st.toggle("Agent Mode", key="agent_mode")
# 5h — Settings expander: file context toggle, model, token limit, custom prompt.

View File

@ -126,7 +126,7 @@ def run_active_file():
except SyntaxError as e:
result = {"stdout": "", "stderr": str(e), "return_code": -1, "ast_error": True}
st.session_state.exec_results[active_file] = result
debug_logger.log_error(f"Syntax error: {e}")
logger.error("Syntax error: %s", e)
return result
with st.spinner(f"Running {Path(active_file).name}..."):

View File

@ -253,14 +253,29 @@ def build_arborist_tree(tree, parent_path=Path()):
def render_filetree_arborist(tree):
"""Render the interactive file tree and return the currently selected node dict."""
"""Render the interactive file tree and return the currently selected node dict.
Passes the active file's relative path as ``selection`` so the tree always
highlights whichever file is currently open in the editor, even when the
user switches tabs instead of clicking the tree.
"""
data = build_arborist_tree(tree)
# Compute the node-ID of the currently active file (posix relative path)
# so the tree highlights it regardless of how the tab was opened.
active_selection = None
active_file = st.session_state.get("active_file")
if active_file:
try:
active_selection = str(Path(active_file).relative_to(fm.base_path).as_posix())
except ValueError:
pass
selected = tree_view(
data=data,
icons={"open": "📂", "closed": "📁"},
height=400,
selection=None,
selection=active_selection,
select_internal_nodes=True, # allow clicking folder names, not just files
open_by_default=True
)

View File

@ -78,6 +78,10 @@ def init_state():
if "code_execution_output" not in st.session_state:
st.session_state.code_execution_output = ""
# Per-file execution results: {file_path: {stdout, stderr, return_code, ast_error}}
if "exec_results" not in st.session_state:
st.session_state.exec_results = {}
# ── Chat state ────────────────────────────────────────────────────────────
# Flat list of {"role": ..., "content": ...} dicts rendered as chat bubbles.