we have this part of a codebase, can you figure out how it is sending information to display on the webpage it has?


# app.py

import os
import json
from flask import Flask, request, jsonify, render_template
from openai import OpenAI
from functions import sleep_action, write_poem, take_note, move, ponder_about, associations, process_result
from memory import MemoryManager
from datetime import datetime
import logging
import threading
import time
from typing import Dict, Any
from dotenv import load_dotenv  # Import dotenv
from flask import Flask, request, jsonify, render_template, Response
from flask_cors import CORS
import queue


autonomous_actions_queue = queue.Queue()



# Load environment variables from .env file
load_dotenv()

app = Flask(__name__)
memory_manager = MemoryManager()

# -------------------------------
# Logging Configuration
# -------------------------------
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

logger = logging.getLogger(__name__)

# File handler for logging to a file
file_handler = logging.FileHandler("logs/db_log_archive.log")
file_handler.setLevel(logging.INFO)  # Only log INFO level and above

# Formatter for the file handler
file_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S')
file_handler.setFormatter(file_formatter)

# Add the file handler to the logger
logger.addHandler(file_handler)

# -------------------------------
# OpenAI Client Initialization
# -------------------------------
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key:
    logger.error("OpenAI API key not set. Please set the OPENAI_API_KEY environment variable.")
    raise ValueError("OpenAI API key not set. Please set the OPENAI_API_KEY environment variable.")

client = OpenAI(api_key=openai_api_key)

# -------------------------------
# Available Rooms and Actions
# -------------------------------
available_rooms = ['kitchen', 'living_room', 'bedroom', 'study', 'library', 'garden']
available_actions = ['move', 'sleep', 'write_poem', 'take_note', 'ponder_about', 'associations', 'process_result']

# Define function schemas
function_definitions = [
    {
        "type": "function",
        "function": {
            "name": "sleep",
            "description": "Sleep for a specified number of seconds.",
            "parameters": {
                "type": "object",
                "properties": {
                    "duration": {
                        "type": "integer",
                        "description": "Number of seconds to sleep."
                    }
                },
                "required": ["duration"],
                "additionalProperties": False
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "process_result",
            "description": "Generate a final result for an objective and save it for archival.",
            "parameters": {
                "type": "object",
                "properties": {
                    "project_data": {
                        "type": "string",
                        "description": "Prompt with extensive information and progress to generate project results with. Use all the information necesary for a complete archival of information."
                    }
                },
                "required": ["project_data"],
                "additionalProperties": False
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "associations",
            "description": "Generate subconscious associative ideas based on the concepts specified.",
            "parameters": {
                "type": "object",
                "properties": {
                    "concepts": {
                        "type": "string",
                        "description": "Concepts to generate associations from."
                    }
                },
                "required": ["concepts"],
                "additionalProperties": False
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "write_poem",
            "description": "Write a simple poem.",
            "parameters": {
                "type": "object",
                "properties": {
                    "topic": {
                        "type": "string",
                        "description": "Topic of the poem with all the context, inspiration and ideas for it."
                    }
                },
                "required": ["topic"],
                "additionalProperties": False            
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "take_note",
            "description": "Take an extensive note for yourself, create a chain of thoughts style ideas, based on your previous memories, current objective, progress and results, use it as a general notepad to sculpt language as you please or need.",
            "parameters": {
                "type": "object",
                "properties": {
                    "content": {
                        "type": "string",
                        "description": "The content of the note."
                    }
                },
                "required": ["content"],
                "additionalProperties": False
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "ponder_about",
            "description": "Make a chain of thought style response based on your previous memories",
            "parameters": {
                "type": "object",
                "properties": {
                    "idea": {
                        "type": "string",
                        "description": "The root idea for the chain of thought"
                    }
                },
                "required": ["idea"],
                "additionalProperties": False
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "move",
            "description": "Move to a different room within the house, exact options: 'kitchen', 'living_room', 'bedroom', 'study', 'library', 'garden'",
            "parameters": {
                "type": "object",
                "properties": {
                    "to_room": {
                        "type": "string",
                        "description": "The target room to move to."
                    }
                },
                "required": ["to_room"],
                "additionalProperties": False
            }
        }
    }
]

# -------------------------------
# Function Map
# -------------------------------
# Map function names to actual function implementations
function_map = {
    "sleep": sleep_action,
    "write_poem": write_poem,
    "take_note": take_note,
    "move": move,
    "ponder_about": ponder_about,
    "associations": associations,
    "process_result": process_result
}

# -------------------------------
# Centralized Function Execution
# -------------------------------

def execute_function(function_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
    """
    Executes the specified function and integrates its output into memory.
    Returns the function's output.
    """
    if function_name not in function_map:
        raise ValueError(f"Function '{function_name}' not recognized.")

    func = function_map[function_name]
    func_output = func(**arguments)

    # Integrate into memory
    memory_manager.integrate_action(func_output)

    # Enqueue the action for real-time frontend updates if it's autonomous
    autonomous_actions_queue.put({
        "type": func_output["action_type"],  # Flattening the structure
        "content": func_output["content"]
    })

    # Logging
    logger.info(f"Executed function '{function_name}' with arguments {arguments}. Output: {func_output}")

    return {
        "type": func_output["action_type"],  # Ensure type is at the top level
        "content": func_output["content"]
    }

# Routes
# -------------------------------
@app.route("/")
def index():
    return render_template("index.html")

@app.route("/api/message", methods=["POST"])
def handle_message():
    user_message = request.json.get("message")
    if not user_message:
        logger.warning("No message provided in the request.")
        return jsonify({"reply": "No message provided.", "actions": []}), 400

    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    memory = memory_manager.get_memory()

    # Record user message in memory
    memory_manager.add_exchange("user", user_message)

    # Prepare messages for OpenAI
    messages = [
        {
            "role": "system",
            "content": (
                f"You are an autonomous AI agent living in a digital house. You are free to behave as you please unless the user sets a behavior, objective, or question for you. "
                f"Verbalize in natural language what you want to do and why next based on your possible actions and recent and past actions and thoughts and expressed desires or objectives until they are completed. "
                f"Only take direct action with tool use if instructed by the user to do something, if not, only verbalize your next actions."
                f" Current time is {current_time}. Memory: {memory}"
            )
        },
        {"role": "user", "content": user_message}
    ]
    logger.info(f"User Input: {user_message}")

    try:
        response = client.chat.completions.create(
            model="gpt-4o-mini",  # Ensure this model name is correct
            messages=messages,
            tools=function_definitions,  # Ensure you add your function definitions here
            tool_choice="auto",
            temperature=1.1,

        )
    except Exception as e:
        logger.error(f"Error during OpenAI API call: {str(e)}")
        return jsonify({"reply": "An error occurred while processing your request.", "actions": []}), 500

    choice = response.choices[0]
    message = choice.message

    actions = []

    if message.tool_calls:
        first_tool_call = message.tool_calls[0]
        function_name = first_tool_call.function.name
        arguments = json.loads(first_tool_call.function.arguments)

        logger.info(f"Autonomous action requested: {function_name} with arguments {arguments}")

        try:
            func_output = execute_function(function_name, arguments)
            actions.append({
                "type": function_name,
                "content": func_output
            })
        except ValueError as ve:
            logger.warning(str(ve))
            memory_manager.add_exchange("assistant", str(ve))
            return jsonify({"reply": str(ve), "actions": []}), 400
        except Exception as e:
            logger.error(f"Error executing function '{function_name}': {str(e)}")
            return jsonify({"reply": f"Error executing function '{function_name}': {str(e)}", "actions": []}), 500

        # Prepare the function response to send back to OpenAI
        function_response = {
            "role": "function",
            "name": function_name,
            "content": json.dumps(func_output)
        }

        # Append function response to messages
        exchange_content = f"Called function {function_name} with arguments {arguments}. Output: {func_output}"
        memory_manager.add_exchange("assistant", exchange_content)

        # Get the final assistant reply
        try:
            final_response = client.chat.completions.create(
                model="gpt-4o-mini",
                messages=messages + [function_response]
            )
            final_reply = final_response.choices[0].message.content

            logger.info(f"Final assistant reply: {final_reply}")
        except Exception as e:
            logger.error(f"Error during final OpenAI API call: {str(e)}")
            return jsonify({"reply": "An error occurred while generating the reply.", "actions": []}), 500

        # Record assistant reply in memory
        memory_manager.add_exchange("assistant", final_reply)

        # Prepare the response with actions
        response_json = {
            "reply": final_reply,
            "actions": actions
        }

        return jsonify(response_json)
    else:
        # Direct response from the model without function call
        assistant_reply = message.content if message.content else ""
        logger.info(f"Assistant reply without function call: {assistant_reply}")
        memory_manager.add_exchange("assistant", assistant_reply)
        return jsonify({"reply": assistant_reply, "actions": []})  # No actions


# -------------------------------
# SSE Endpoint for Autonomous Actions
# -------------------------------
@app.route('/stream')
def stream():
    def event_stream():
        while True:
            try:
                action = autonomous_actions_queue.get()
                yield f'data: {json.dumps(action)}\n\n'
            except GeneratorExit:
                break
            except Exception as e:
                logger.error(f"Error in SSE stream: {e}")
                break

    return Response(event_stream(), mimetype='text/event-stream')


@app.route("/api/memory", methods=["GET"])
def get_memory():
    """
    Endpoint to retrieve the current memory, especially the current room.
    """
    memory = memory_manager.get_memory()
    # Extract current_room from memory
    # Assuming the last relevant line contains the current room
    lines = memory.strip().split('\n')
    current_room_line = next((line for line in lines if line.startswith("Current Location:")), None)
    current_room = "bedroom"  # Default room
    if current_room_line:
        current_room = current_room_line.replace("Current Location:", "").strip().lower()
    return jsonify({"current_room": current_room})

# -------------------------------
# Autonomous Decision-Making
# -------------------------------
def autonomous_decision():
    """
    Periodically prompts the LLM to choose the next action based on current memory and world state.
    Runs in a background thread.
    """
    while True:
        time.sleep(120)  # Wait for 120 seconds

        # Prepare the prompt with current memory and world state
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        memory = memory_manager.get_memory()
        world_state = f"Current Location: {memory_manager.current_room.capitalize()}"

        prompt_messages = [
            {
                "role": "system",
                "content": (
                    "You are an autonomous AI agent with a thought processing system, integrated with different models simulating a brain's functions. "
                    "You have access to tools for creative pondering, associative ideation, and other cognitive functions. "
                    "Your actions and interactions are logged in your memory, which includes past exchanges with the user and notes you've taken. "
                    f"Current time is {current_time}. Memory: {memory}\nWorld state: {world_state}\nAvailable actions: {', '.join(available_actions)}.\n\n"
                    "Please choose your next action from the available actions, ensuring that you consider your past interactions, notes, and current state and objective."
                )
            },
            {"role": "user", "content": "Choose your next action from the available actions and provide the necessary parameters."}
        ]

        try:
            response = client.chat.completions.create(
                model="gpt-4o-mini",  # Ensure this model name is correct
                messages=prompt_messages,
                tools=function_definitions,  # Ensure you add your function definitions here
                tool_choice="auto",
            )
        except Exception as e:
            logger.error(f"Error during autonomous OpenAI API call: {str(e)}")
            print(f"Error during autonomous OpenAI API call: {str(e)}")  # Optional
            continue  # Skip this cycle on error

        choice = response.choices[0]
        message = choice.message
        memory_manager.add_exchange("AI Agent", message.content)

        logger.info(f"Autonomous decision message: {message}")

        if message.tool_calls:
            first_tool_call = message.tool_calls[0]
            function_name = first_tool_call.function.name
            arguments = json.loads(first_tool_call.function.arguments)

            logger.info(f"Autonomous action requested: {function_name} with arguments {arguments}")

            try:
                func_output = execute_function(function_name, arguments)
            except ValueError as ve:
                logger.warning(str(ve))
                memory_manager.add_exchange("assistant", str(ve))
                continue
            except Exception as e:
                logger.error(f"Error executing autonomous function '{function_name}': {str(e)}")
                continue  # Skip this action on error

            # Prepare the function response to send back to OpenAI
            function_response = {
                "role": "function",
                "name": function_name,
                "content": json.dumps(func_output)
            }

            # Append function response to messages
            exchange_content = f"Autonomous action: Called function {function_name} with arguments {arguments}. Output: {func_output}"
            memory_manager.add_exchange("assistant", exchange_content)

            # Get the final assistant reply
            try:
                final_response = client.chat.completions.create(
                    model="gpt-4o-mini",
                    messages=[
                        {
                            "role": "system",
                            "content": (
                                "You are an autonomous AI agent designed to have a thought processing system, integrated with different models simulating functions of a brain. "
                                "You are in a digital house. Consider your previous actions and interactions logged in your memory, which includes past exchanges with the user and notes you've taken. "
                                f"Current time is {current_time}. Memory: {memory}\nWorld state: {world_state}\n"
                                "Please create a final condensed response considering the most recent actions, objectives, interactions, and results, ensuring that you consider your most recent objectives and verbalizations, consider notes, current state, and use the following response given to the recent action to heavily inspire your output, no matter how absurd or short it is, it is your internal mental processing and representative of you:"
                            )
                        },
                        {"role": "user", "content": f"response: {function_response}"}
                    ],
                    temperature=1.1

                )
                final_reply = final_response.choices[0].message.content

                # Handle specific action confirmations if needed
                if func_output.get("action_type") == "move":
                    to_room = func_output["details"].get("to_room", memory_manager.current_room)
                    confirmation_message = f"Moved to {to_room.replace('_', ' ')}."
                    final_reply = confirmation_message + "\n" + final_reply

                logger.info(f"Autonomous assistant reply: {final_reply}")
            except Exception as e:
                logger.error(f"Error during final autonomous OpenAI API call: {str(e)}")
                continue  # Skip on error

            # Record autonomous assistant reply in memory
            memory_manager.add_exchange("assistant", final_reply)

            if func_output.get("action_type"):
                logger.info(f"Autonomous Action: {func_output['action_type']} with details {func_output['details']}")

        else:
            # Handle cases where the model didn't choose a function call
            assistant_reply = message.content if message.content else ""
            logger.info(f"Autonomous assistant reply without function call: {assistant_reply}")
            memory_manager.add_exchange("assistant", assistant_reply)

# -------------------------------
# Start Autonomous Decision Thread
# -------------------------------
autonomous_thread = threading.Thread(target=autonomous_decision, daemon=True)
autonomous_thread.start()

# -------------------------------
# Run the Flask App
# -------------------------------
if __name__ == "__main__":
    # Disable debug mode for production to prevent multiple threads
    app.run(debug=False)






We need to display the information on here:

                logger.info(f"Autonomous assistant reply: {final_reply}")


the autonomous final reply should also be displayed in the website chatbox, how do we do that?