import streamlit as st import os import glob import asyncio import sys # Add project root sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) from appagents.OrchestratorAgent import OrchestratorAgent from agents import Runner, trace, SQLiteSession from agents.exceptions import InputGuardrailTripwireTriggered # ----------------------------- # Load predefined prompts # ----------------------------- def load_prompts(folder="prompts"): prompts = [] prompt_labels = [] for file_path in glob.glob(os.path.join(folder, "*.txt")): with open(file_path, "r", encoding="utf-8") as f: content = f.read().strip() if content: prompts.append(content) prompt_labels.append(os.path.basename(file_path).replace("_", " ").replace(".txt", "").title()) return prompts, prompt_labels prompts, prompt_labels = load_prompts() # ----------------------------- # Streamlit page config # ----------------------------- st.set_page_config(page_title="AI Chat", layout="wide") # ----------------------------- # Custom CSS (chat, hero banner, input) # ----------------------------- st.markdown(""" """, unsafe_allow_html=True) # ----------------------------- # Session state defaults # ----------------------------- if "chat_history" not in st.session_state: st.session_state.chat_history = [] # newest-first if "input_value" not in st.session_state: st.session_state.input_value = "" if "pending_response" not in st.session_state: st.session_state.pending_response = False if "pending_message" not in st.session_state: st.session_state.pending_message = None if "auto_send_prompt" not in st.session_state: st.session_state.auto_send_prompt = None # Create (or reuse) a persistent SQLite session import uuid # Generate a unique session ID for this browser session if "ai_session_id" not in st.session_state: st.session_state.ai_session_id = str(uuid.uuid4()) session_id = st.session_state.ai_session_id # Create a unique SQLite session per user if "ai_session" not in st.session_state: st.session_state.ai_session = SQLiteSession(f"conversation_{session_id}.db") session = st.session_state.ai_session # ----------------------------- # Async AI response # ----------------------------- async def get_ai_response(prompt: str) -> str: try: agent = OrchestratorAgent.create() with trace("Chatbot Search Agent Run"): result = await Runner.run(agent, prompt, session=session) return result.final_output except InputGuardrailTripwireTriggered as e: reasoning = getattr(e, "reasoning", None) \ or getattr(getattr(e, "output", None), "reasoning", None) \ or getattr(getattr(e, "guardrail_output", None), "reasoning", None) \ or "Guardrail triggered, but no reasoning provided." return f"⚠️ Guardrail Blocked Input:\n\n**Reason:** {reasoning}" # ----------------------------- # Desktop Sidebar Quick Prompts # ----------------------------- with st.sidebar.container() if st.config.get_option("server.headless") is False else st.container() as container: st.markdown('