import streamlit as st from crew_initializer import initialize_crew from utils.pdf_generator import generate_pdf import json import logging import re # Configure logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # Custom JSON Encoder class CustomJSONEncoder(json.JSONEncoder): def default(self, obj): try: # Convert objects with __dict__ attributes to dictionaries if hasattr(obj, "__dict__"): return obj.__dict__ return super().default(obj) except TypeError: return str(obj) # Fallback for unsupported types # Hardcoded credentials USER_CREDENTIALS = {"username": "admin", "password": "P@ssword123"} def authenticate_user(): """Authenticate the user with a username and password""" st.sidebar.header("Login") username = st.sidebar.text_input("Username") password = st.sidebar.text_input("Password", type="password") if st.sidebar.button("Login"): if username == USER_CREDENTIALS["username"] and password == USER_CREDENTIALS["password"]: st.session_state.authenticated = True st.sidebar.success("Login successful!") st.rerun() # Rerun to clear login form and show the app else: st.sidebar.error("Invalid username or password.") def main(): """ Main entry point for the Streamlit application. Handles user input, executes tasks, and displays results. """ # Ensure authentication state is properly initialized if 'authenticated' not in st.session_state: st.session_state.authenticated = False # Authenticate user if not authenticated if not st.session_state.authenticated: authenticate_user() return # Exit early if not authenticated # Once authenticated, proceed with the main application st.title("**Company Researcher Tool**") st.sidebar.header("Provide Company Details") company_name = st.sidebar.text_input("Enter the Company URL:") # Show the "Run Analysis" button if the user is authenticated if st.session_state.authenticated: # Show the button whether or not the company name is entered run_analysis_button = st.sidebar.button("Run Analysis") # Only run the analysis when the button is clicked if run_analysis_button: st.markdown(f"### **Running analysis for:** {company_name}", unsafe_allow_html=True) with st.spinner("Executing tasks, please wait..."): try: crew = initialize_crew() result = crew.kickoff(inputs={"company": company_name}) result_serialized = json.loads(json.dumps(result, cls=CustomJSONEncoder)) # Extracting the raw summary report summary_report = result_serialized.get('tasks_output', [{}])[0].get('raw', '') # Formatting the raw content into structured report structured_report = format_report(summary_report) st.markdown(f"### **Summary Report**", unsafe_allow_html=True) st.markdown(structured_report, unsafe_allow_html=True) pdf_buffer = generate_pdf(result_serialized) st.download_button( label="📄 Download Report (PDF)", data=pdf_buffer, file_name=f"{company_name}_report.pdf", mime="application/pdf" ) except Exception as e: logging.error(f"Error during analysis: {str(e)}") st.error(f"An error occurred: {str(e)}") else: st.info("Please enter a company name to run the analysis.") def format_report(raw_text): """ Takes raw text (markdown/structured content) and formats it to create a more readable, structured report with bold headers. """ # This pattern looks for headings with a number followed by bold text and a colon (e.g. 1. **Heading**:) heading_pattern = r'(\d+\.)\s?(\*\*[^*]+\*\*):' # Replace headings with Markdown syntax (e.g., ## **Heading**:) formatted_report = re.sub(heading_pattern, r'## \2:', raw_text) # Replace **bold text** with proper markdown formatting formatted_report = re.sub(r'\*\*(.*?)\*\*', r'**\1**', formatted_report) # Replace **bold** with HTML to control the bolding in headers only formatted_report = re.sub(r'\*\*(.*?)\*\*', r'\1', formatted_report) # Now use Markdown for the rest of the text, with normal text not bold formatted_report = formatted_report.replace("\n", "
") # Use line breaks for formatting return formatted_report if __name__ == "__main__": main()