import streamlit as st import requests import logging # Configure logging to output to terminal for debugging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s" ) logger = logging.getLogger(__name__) # API endpoint # BASE_URL = "http://localhost:31337" BASE_URL = "https://slop.unturf.com" def main(): st.title("SLOP Streamlit with Dynamic Models") st.markdown( "[Explore API Documentation](https://slop.unturf.com/openapi/)", unsafe_allow_html=True, ) page = st.sidebar.selectbox( "Choose a feature", ["Chat", "Tools", "Memory", "Resources", "Pay"] ) if page == "Chat": chat_interface() elif page == "Tools": tools_interface() elif page == "Memory": memory_interface() elif page == "Resources": resources_interface() elif page == "Pay": pay_interface() def chat_interface(): st.header("Chat") try: response = requests.get(f"{BASE_URL}/models", timeout=5) response.raise_for_status() models = response.json()["models"] except requests.RequestException as e: st.warning(f"Could not fetch models: {str(e)}") models = [] selected_model = st.selectbox( "Select Model", models if models else ["No models available"] ) if "chat_history" not in st.session_state: st.session_state.chat_history = [] for entry in st.session_state.chat_history: st.write(f"**User**: {entry['user']}") st.write(f"**Assistant**: {entry['assistant']}") with st.form(key="chat_form", clear_on_submit=True): message = st.text_area("Enter your message", height=100, key="chat_input") submit_button = st.form_submit_button(label="Submit", type="primary") st.markdown( """ """, unsafe_allow_html=True, ) if submit_button and message and models: try: response = requests.post( f"{BASE_URL}/chat", json={ "messages": [{"role": "user", "content": message}], "model": selected_model, }, timeout=300, ) response.raise_for_status() assistant_response = response.json()["choices"][0]["message"]["content"] st.session_state.chat_history.append( {"user": message, "assistant": assistant_response} ) st.rerun() except requests.RequestException as e: st.error(f"Error: {str(e)}") def tools_interface(): st.header("Tools") try: response = requests.get(f"{BASE_URL}/tools", timeout=5) response.raise_for_status() tools = response.json()["tools"] except requests.RequestException as e: st.warning(f"Could not fetch tools: {str(e)}") tools = [] if not tools: st.write("No tools available.") return tool_id = st.selectbox("Select a tool", [t["id"] for t in tools]) if tool_id == "calculator": expression = st.text_input("Enter expression (e.g., 2 + 2)") if st.button("Calculate"): try: response = requests.post( f"{BASE_URL}/tools/{tool_id}", json={"expression": expression}, timeout=5, ) response.raise_for_status() st.write(f"Result: {response.json()['result']}") except requests.RequestException as e: st.error(f"Error: {str(e)}") elif tool_id == "greet": name = st.text_input("Enter name") if st.button("Greet"): try: response = requests.post( f"{BASE_URL}/tools/{tool_id}", json={"name": name}, timeout=5 ) response.raise_for_status() st.write(response.json()["result"]) except requests.RequestException as e: st.error(f"Error: {str(e)}") elif tool_id == "slots": st.subheader("Slots") agent_id = st.text_input("Your Agent ID", value="player1") bet = st.number_input("Bet Amount", min_value=1, step=1, value=10) if st.button("Spin"): try: response = requests.post( f"{BASE_URL}/tools/slots", json={"bet": bet, "agent_id": agent_id}, timeout=5, ) response.raise_for_status() result = response.json() if "error" in result: st.error(f"Error: {result['error']}") else: st.write(f"**Result**: {result['explanation']}") st.write(f"**Reels**: {result['game_state']['reels']}") st.write(f"**Payout**: {result['payout']}") st.write(f"**New Balance**: {result['new_balance']}") except requests.RequestException as e: st.error(f"Error: {str(e)}") elif tool_id == "blackjack": st.subheader("Blackjack") agent_id = st.text_input( "Your Agent ID", value="player1", key="blackjack_agent" ) # Initialize session state for blackjack game ID if "blackjack_game_id" not in st.session_state: st.session_state.blackjack_game_id = None logger.debug("Initialized blackjack_game_id as None in session state") # Start a new game if st.session_state.blackjack_game_id is None: bet = st.number_input("Bet Amount", min_value=1, step=1, value=10) if st.button("Start Game"): logger.debug( f"Starting blackjack with bet: {bet}, agent_id: {agent_id}" ) try: response = requests.post( f"{BASE_URL}/tools/blackjack", json={"bet": bet, "agent_id": agent_id}, timeout=5, ) logger.debug( f"POST /tools/blackjack status: {response.status_code}, content: {response.text}" ) response.raise_for_status() result = response.json() if "error" in result: st.error(f"Error: {result['error']}") logger.error(f"Blackjack start error: {result['error']}") else: st.session_state.blackjack_game_id = result["game_id"] logger.debug( f"Set blackjack_game_id: {st.session_state.blackjack_game_id}" ) st.write(f"**Game Started**: {result['explanation']}") st.write( f"**Your Hand**: {result['game_state']['player_hands'][0]} (Total: {result['game_state']['player_totals'][0]})" ) st.write( f"**Dealer’s Up Card**: {result['game_state']['dealer_hand']}" ) st.rerun() except requests.RequestException as e: st.error(f"Error starting blackjack: {str(e)}") logger.error(f"Error starting blackjack: {str(e)}", exc_info=True) else: # Display current game state and allow hit/stand/split try: response = requests.get( f"{BASE_URL}/resources/casino/blackjack/games/{st.session_state.blackjack_game_id}", timeout=5, ) logger.debug( f"GET /resources/.../{st.session_state.blackjack_game_id} status: {response.status_code}, content: {response.text}" ) response.raise_for_status() game_state = response.json()["content"] st.write( f"**Current Game (ID: {st.session_state.blackjack_game_id})**:" ) for i, (hand, total) in enumerate( zip(game_state["player_hands"], game_state["player_totals"]) ): active = ( " (Active)" if i == game_state["active_hand"] and game_state["status"] == "active" else "" ) st.write(f"**Hand {i + 1}{active}**: {hand} (Total: {total})") st.write(f"**Dealer’s Up Card**: {game_state['dealer_hand']}") st.write(f"**Total Bet**: {game_state['bet']}") if game_state["status"] == "active": col1, col2, col3 = st.columns(3) with col1: if st.button("Hit"): logger.debug( f"Sending hit action for game_id: {st.session_state.blackjack_game_id}" ) try: response = requests.post( f"{BASE_URL}/tools/blackjack", json={ "agent_id": agent_id, "game_id": st.session_state.blackjack_game_id, "action": "hit", }, timeout=5, ) logger.debug( f"POST /tools/blackjack (hit) status: {response.status_code}, content: {response.text}" ) response.raise_for_status() result = response.json() if "error" in result: st.error(f"Error: {result['error']}") logger.error(f"Hit error: {result['error']}") else: st.write(f"**Result**: {result['explanation']}") if result["game_complete"]: st.write(f"**Payout**: {result['payout']}") st.write( f"**New Balance**: {result['new_balance']}" ) st.session_state.blackjack_game_id = None logger.debug( "Game completed, reset blackjack_game_id to None" ) st.rerun() except requests.RequestException as e: st.error(f"Error during hit: {str(e)}") logger.error( f"Error during hit: {str(e)}", exc_info=True ) with col2: if st.button("Stand"): logger.debug( f"Sending stand action for game_id: {st.session_state.blackjack_game_id}" ) try: response = requests.post( f"{BASE_URL}/tools/blackjack", json={ "agent_id": agent_id, "game_id": st.session_state.blackjack_game_id, "action": "stand", }, timeout=5, ) logger.debug( f"POST /tools/blackjack (stand) status: {response.status_code}, content: {response.text}" ) response.raise_for_status() result = response.json() if "error" in result: st.error(f"Error: {result['error']}") logger.error(f"Stand error: {result['error']}") else: st.write(f"**Result**: {result['explanation']}") if result["game_complete"]: for outcome in result["outcomes"]: if "win" in outcome.lower(): st.success(outcome) elif "lose" in outcome.lower(): st.error(outcome) else: st.warning(outcome) st.write( f"**Total Payout**: {result['payout']}" ) st.write( f"**New Balance**: {result['new_balance']}" ) st.session_state.blackjack_game_id = None logger.debug( "Game completed, reset blackjack_game_id to None" ) st.rerun() except requests.RequestException as e: st.error(f"Error during stand: {str(e)}") logger.error( f"Error during stand: {str(e)}", exc_info=True ) with col3: can_split = ( len(game_state["player_hands"]) == 1 and len(game_state["player_hands"][0]) == 2 and game_state["player_hands"][0][0] == game_state["player_hands"][0][1] ) if can_split and st.button("Split"): logger.debug( f"Sending split action for game_id: {st.session_state.blackjack_game_id}" ) try: response = requests.post( f"{BASE_URL}/tools/blackjack", json={ "agent_id": agent_id, "game_id": st.session_state.blackjack_game_id, "action": "split", }, timeout=5, ) logger.debug( f"POST /tools/blackjack (split) status: {response.status_code}, content: {response.text}" ) response.raise_for_status() result = response.json() if "error" in result: st.error(f"Error: {result['error']}") logger.error(f"Split error: {result['error']}") else: st.write(f"**Result**: {result['explanation']}") st.rerun() except requests.RequestException as e: st.error(f"Error during split: {str(e)}") logger.error( f"Error during split: {str(e)}", exc_info=True ) except requests.RequestException as e: st.error(f"Error fetching game state: {str(e)}") logger.error(f"Error fetching game state: {str(e)}", exc_info=True) st.session_state.blackjack_game_id = None logger.debug("Reset blackjack_game_id to None due to fetch error") def memory_interface(): st.header("Memory") action = st.radio("Action", ["Store", "Retrieve", "List", "Delete"]) if action == "Store": key = st.text_input("Key") value = st.text_input("Value") if st.button("Store"): try: response = requests.post( f"{BASE_URL}/memory", json={"key": key, "value": value}, timeout=5 ) response.raise_for_status() st.success("Stored successfully!") list_response = requests.get(f"{BASE_URL}/memory", timeout=5) list_response.raise_for_status() keys = list_response.json()["keys"] st.write("Current Memory Keys:", ", ".join(keys) if keys else "None") except requests.RequestException as e: st.error(f"Error: {str(e)}") elif action == "Retrieve": key = st.text_input("Key to retrieve") if st.button("Retrieve"): try: response = requests.get(f"{BASE_URL}/memory/{key}", timeout=5) response.raise_for_status() value = response.json()["value"] st.write(f"Value: {value if value is not None else 'Not found'}") except requests.RequestException as e: st.error(f"Error: {str(e)}") elif action == "List": if st.button("List All Keys"): try: response = requests.get(f"{BASE_URL}/memory", timeout=5) response.raise_for_status() keys = response.json()["keys"] st.write("Memory Keys:", ", ".join(keys) if keys else "None") except requests.RequestException as e: st.error(f"Error: {str(e)}") elif action == "Delete": key = st.text_input("Key to delete") if st.button("Delete"): try: response = requests.delete(f"{BASE_URL}/memory/{key}", timeout=5) response.raise_for_status() st.success("Deleted successfully!") list_response = requests.get(f"{BASE_URL}/memory", timeout=5) list_response.raise_for_status() keys = list_response.json()["keys"] st.write("Current Memory Keys:", ", ".join(keys) if keys else "None") except requests.RequestException as e: st.error(f"Error: {str(e)}") def resources_interface(): st.header("Resources") # Fetch available resources try: response = requests.get(f"{BASE_URL}/resources", timeout=5) response.raise_for_status() resources = response.json()["resources"] except requests.RequestException as e: st.warning(f"Could not fetch resources: {str(e)}") resources = [] if not resources: st.write("No resources available.") return # Select resource for GET resource_id = st.selectbox("Select resource to get", [r["id"] for r in resources]) if st.button("Get Resource"): try: response = requests.get(f"{BASE_URL}/resources/{resource_id}", timeout=5) response.raise_for_status() result = response.json() if "error" in result: st.error(f"Error: {result['error']}") elif "resources" in result: # Prefix search result st.write("Nested Resources Found:") for res in result["resources"]: st.write(f"- **{res['id']}**: {res['content']}") else: # Exact match st.write(f"**{result['id']}**: {result['content']}") except requests.RequestException as e: st.error(f"Error: {str(e)}") # Form for updating/creating a resource st.subheader("Update or Create Resource") with st.form(key="resource_form"): new_resource_id = st.text_input("Resource ID", value=resource_id) content = st.text_area("Content", height=100) submit_button = st.form_submit_button(label="Update/Create", type="primary") if submit_button and new_resource_id and content: try: response = requests.put( f"{BASE_URL}/resources/{new_resource_id}", json={"content": content}, timeout=5, ) response.raise_for_status() result = response.json() st.success( f"Resource {result['resource']['id']} updated/created successfully!" ) st.write( f"**{result['resource']['id']}**: {result['resource']['content']}" ) except requests.RequestException as e: st.error(f"Error: {str(e)}") def pay_interface(): st.header("Pay") amount = st.number_input("Amount", min_value=0.0, step=0.01) if st.button("Pay"): try: response = requests.post( f"{BASE_URL}/pay", json={"amount": amount}, timeout=5 ) response.raise_for_status() st.write(f"Transaction ID: {response.json()['transaction_id']}") st.write(f"Status: {response.json()['status']}") except requests.RequestException as e: st.error(f"Error: {str(e)}") if __name__ == "__main__": main()