import streamlit as st from streamlit_ace import st_ace import subprocess import time import re import asyncio import json import uuid import os from code_assistant_runnable import get_runnable from langchain_core.messages import SystemMessage, AIMessage, HumanMessage, ToolMessage # Set up page configuration st.set_page_config(page_title="AI Code Editor", page_icon=":computer:", layout="wide") @st.cache_resource def create_code_assistant_instance(): try: # Import torch first to ensure proper initialization import torch torch.set_grad_enabled(False) # Disable gradients since we're only doing inference return get_runnable() except Exception as e: st.error(f"Error initializing chatbot: {str(e)}") return None chatbot = create_code_assistant_instance() # Initialize session states if 'messages' not in st.session_state: st.session_state.messages = [ AIMessage(content="Hello, I am your coding assistant. How can I help you?"), ] if 'editor_code' not in st.session_state: st.session_state.editor_code = '' # Constants EDITOR_HEIGHT = 400 OUTPUT_HEIGHT = 150 # Minimal CSS for styling st.markdown(""" """, unsafe_allow_html=True) def analyze_code(code, language): """ Basic code analysis function that looks for common issues """ analysis = [] if language == "python": # Check for basic Python issues if "while" in code and "break" not in code: analysis.append("⚠️ While loop detected without break condition - check for infinite loops") if "except:" in code and "except Exception:" not in code: analysis.append("⚠️ Bare except clause detected - consider catching specific exceptions") if "print" in code and "if __name__ == '__main__':" not in code: analysis.append("💡 Consider adding main guard for scripts with print statements") if re.search(r'^\s+', code, re.MULTILINE): analysis.append("🔍 Mixed indentation detected - check spacing") elif language == "rust": if "unwrap()" in code: analysis.append("⚠️ Usage of unwrap() detected - consider proper error handling") if "mut" not in code and len(code) > 50: analysis.append("💡 No mutable variables detected - verify if intentional") if not analysis: analysis.append("✅ No immediate issues detected in the code") return "\n".join(analysis) def dummy_ai_response(question, code_context, language): """ Dummy AI response function with basic code context awareness """ time.sleep(1) # Simulate processing time if "debug" in question.lower(): return f"Here's my analysis of your {language} code:\n" + analyze_code(code_context, language) if "how" in question.lower() and "implement" in question.lower(): return f"To implement this in {language}, you might want to consider:\n1. Breaking down the problem\n2. Using appropriate data structures\n3. Following {language} best practices" if "error" in question.lower() or "not working" in question.lower(): return "Let me help you debug that. Could you:\n1. Share the specific error message\n2. Describe what you expected to happen\n3. Describe what actually happened" return f"I see you're working with {language}. Could you clarify what specific help you need with your code?" def run_python_code(code): try: with open("temp_code.py", "w") as f: f.write(code) result = subprocess.run(["python", "temp_code.py"], capture_output=True, text=True) return result.stderr if result.stderr else result.stdout except Exception as e: return f"Error: {e}" def run_rust_code(code): with open('code.rs', 'w') as file: file.write(code) compile_process = subprocess.Popen(['rustc', 'code.rs'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) compile_output, compile_errors = compile_process.communicate() if compile_process.returncode != 0: return f"Compilation Error: {compile_errors}" run_process = subprocess.Popen(['./code'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) run_output, run_errors = run_process.communicate() return run_output if not run_errors else run_errors def run_js_code(): pass def dummy_auto_complete(code: str, language: str = None) -> str: """ Dummy function to simulate LLM code completion Args: code (str): The incomplete code in the editor language (str, optional): Selected programming language Returns: str: The completed code """ time.sleep(2) # Simulate processing time # Example completions based on language completions = { "python": """# Function to calculate sum def calculate_sum(a: int, b: int) -> int: '''Calculate sum of two integers''' return a + b""", "javascript": """// Function to calculate sum function calculateSum(a, b) { return a + b; }""", "rust": """// Function to calculate sum fn calculate_sum(a: i32, b: i32) -> i32 { a + b }""" } # Return language-specific completion or default to Python return completions.get(language, completions["python"]) # Sidebar settings with st.sidebar: st.title("SolCoder") st.header("Solana AI Code Editor") theme = st.selectbox("Editor Theme", ["monokai", "github", "solarized_dark", "solarized_light", "dracula"]) font_size = st.slider("Font Size", 12, 24, 14) show_gutter = st.checkbox("Show Line Numbers", value=True) language = st.selectbox("Language", ["python", "javascript", "rust"], index=0) # Create two columns for main layout col1, col2 = st.columns([3, 2]) # Left Column - Code Editor and Output with col1: st.subheader("") st.subheader("Code Editor") st.markdown("Write your code below and use the buttons to run or debug") # Code editor editor = st_ace( value=st.session_state.editor_code, language=language, theme=theme, font_size=font_size, show_gutter=show_gutter, auto_update=True, height=EDITOR_HEIGHT, key="editor" ) # Buttons - Modified to include three columns button_cols = st.columns(3) with button_cols[0]: auto_complete_btn = st.button("Auto-Complete", use_container_width=True) with button_cols[1]: run_btn = st.button("Run Code", use_container_width=True) with button_cols[2]: debug_btn = st.button("Debug Code", use_container_width=True) # Handle auto-complete button click if auto_complete_btn: with st.spinner("Generating code completion..."): try: # Get completed code from dummy function completed_code = dummy_auto_complete(st.session_state.editor_code, language) st.markdown(f'
AI Assistant Chat
', unsafe_allow_html=True) st.subheader("") st.subheader("Code Assistant Agent") # conversation def validate_message(message): """Validate message before adding to history""" if not isinstance(message, (AIMessage, HumanMessage)): return False if not message.content or not isinstance(message.content, str): return False return True def add_message_to_history(message): """Safely add message to chat history""" if validate_message(message): st.session_state.messages.append(message) return True return False # Update message display section for message in st.session_state.messages: if isinstance(message, AIMessage): with st.chat_message("AI"): # Handle code blocks in message content = message.content if "```" in content: parts = content.split("```") for i, part in enumerate(parts): if i % 2 == 0: # Regular text if part.strip(): st.markdown(part) else: # Code block st.code(part) else: st.markdown(content) elif isinstance(message, HumanMessage): with st.chat_message("Human"): st.markdown(message.content) # Clear chat button if st.button("Clear Chat", use_container_width=True): st.session_state.messages = [] st.rerun() if prompt := st.chat_input("Ask about writing solana code..."): user_message = HumanMessage(content=prompt) # Add user message to history if add_message_to_history(user_message): with st.chat_message("AI"): # Create a placeholder for the loading indicator response_placeholder = st.empty() # Show loading message with response_placeholder: with st.spinner("AI is thinking..."): try: # Get AI response ai_response = chatbot.invoke({ "messages": [("user", prompt)], "iterations": 0, "error": "" }) # Format and add AI response formatted_response = format_ai_response(ai_response) ai_message = AIMessage(content=formatted_response) # Clear the loading indicator and show the response response_placeholder.empty() st.markdown(formatted_response) # Add to history add_message_to_history(ai_message) # Only rerun after successful processing st.rerun() except Exception as e: response_placeholder.error(f"Error generating response: {str(e)}")