# pages/2_Control_Panel.py (Modifications for Step 3) import streamlit as st import time import json # Use the updated API-backed functions from .ui_utils import ( list_all_agents, get_agent_status, get_agent_logs, start_agent, stop_agent, update_agent_config, ) st.set_page_config(page_title="Agent Control Panel", layout="wide") st.title("🕹️ Multi-Agent Control Panel") st.caption("Manage and monitor Tensorus agents via API.") # Fetch agent list from API agent_list = list_all_agents() if not agent_list: st.error("Could not fetch agent list from API. Please ensure the backend is running and reachable.") st.stop() # Create a mapping from name to ID for easier selection # Handle potential duplicate names if necessary, though IDs should be unique agent_options = {agent['name']: agent['id'] for agent in agent_list} # Add ID to name if names aren't unique (optional robustness) # agent_options = {f"{agent['name']} ({agent['id']})": agent['id'] for agent in agent_list} selected_agent_name = st.selectbox("Select Agent:", options=agent_options.keys()) if selected_agent_name: selected_agent_id = agent_options[selected_agent_name] st.divider() st.subheader(f"Control: {selected_agent_name} (`{selected_agent_id}`)") # Use session state to store fetched status and logs for the selected agent # This avoids refetching constantly unless a refresh is triggered agent_state_key = f"agent_status_{selected_agent_id}" agent_logs_key = f"agent_logs_{selected_agent_id}" # Button to force refresh status and logs if st.button(f"🔄 Refresh Status & Logs##{selected_agent_id}"): # Unique key per agent st.session_state[agent_state_key] = get_agent_status(selected_agent_id) st.session_state[agent_logs_key] = get_agent_logs(selected_agent_id) st.rerun() # Rerun to display refreshed data # Fetch status if not in session state or refresh button wasn't just clicked if agent_state_key not in st.session_state: st.session_state[agent_state_key] = get_agent_status(selected_agent_id) status_info = st.session_state[agent_state_key] if status_info: status = status_info.get('status', 'unknown') status_color = "green" if status in ["running", "starting"] else ("orange" if status in ["stopping"] else ("red" if status in ["error"] else "grey")) st.markdown(f"Current Status: :{status_color}[**{status.upper()}**]") last_log_ts = status_info.get('last_log_timestamp') if last_log_ts: st.caption(f"Last Log Entry (approx.): {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(last_log_ts))}") else: st.error(f"Could not retrieve status for agent '{selected_agent_name}'.") # Control Buttons (Now call API functions) col1, col2, col3 = st.columns([1, 1, 5]) is_running = status_info and status_info.get('status') == 'running' is_stopped = status_info and status_info.get('status') == 'stopped' with col1: start_disabled = not is_stopped # Disable if not stopped if st.button("▶️ Start", key=f"start_{selected_agent_id}", disabled=start_disabled): if start_agent(selected_agent_id): # API call returns success/fail # Trigger refresh after short delay to allow backend state change (optimistic) time.sleep(1.0) # Clear state cache and rerun if agent_state_key in st.session_state: del st.session_state[agent_state_key] if agent_logs_key in st.session_state: del st.session_state[agent_logs_key] st.rerun() with col2: stop_disabled = not is_running # Disable if not running if st.button("⏹️ Stop", key=f"stop_{selected_agent_id}", disabled=stop_disabled): if stop_agent(selected_agent_id): # API call returns success/fail time.sleep(1.0) if agent_state_key in st.session_state: del st.session_state[agent_state_key] if agent_logs_key in st.session_state: del st.session_state[agent_logs_key] st.rerun() st.divider() # Configuration & Logs tab1, tab2 = st.tabs(["Configuration", "Logs"]) with tab1: if status_info and 'config' in status_info: current_config = status_info['config'] st.write("Current configuration:") st.json(current_config) with st.expander("Edit configuration"): form = st.form(key=f"cfg_form_{selected_agent_id}") config_text = form.text_area( "Configuration JSON", value=json.dumps(current_config, indent=2), height=200, ) submitted = form.form_submit_button("Update") if submitted: try: new_cfg = json.loads(config_text) if update_agent_config(selected_agent_id, new_cfg): if agent_state_key in st.session_state: del st.session_state[agent_state_key] time.sleep(0.5) st.rerun() except json.JSONDecodeError as e: form.error(f"Invalid JSON: {e}") else: st.warning("Configuration not available.") with tab2: st.write("Recent logs (fetched from API):") # Fetch logs if not in session state if agent_logs_key not in st.session_state: st.session_state[agent_logs_key] = get_agent_logs(selected_agent_id) logs = st.session_state[agent_logs_key] if logs is not None: st.code("\n".join(logs), language="log") else: st.error("Could not retrieve logs.") else: st.info("Select an agent from the dropdown above.")